2013-01-15 16 views
8

Ho due repository. Di volta in volta, voglio unire il contenuto di other in main. Tuttavia l'unione ignora i file cancellati. Mi spiego con un esempio:Git ignora il file cancellato sulla fusione

mkdir -p test/main test/other 

cd test/other/ 
git init 
touch one two three 
git add . 
git commit -m "Add one, two and three." 

cd ../main/ 
git init 
touch four 
git add . 
git commit -m "Add four." 

Aggiungi other-main come remoto.

git remote add other ../other/ 
git fetch other 

Unire il suo contenuto.

git merge --squash other/master 
git commit -m "Merge other." 

Aggiunge i file correttamente. Ora, rimuovere un file in other.

cd ../other/ 
git rm two 
git commit -m "Remove two." 

Unisci modifiche in main.

cd ../main/ 
git fetch other 
git merge --squash other/master 

Dopo l'unione git status dice:

# On branch master 
nothing to commit (working directory clean) 

mi aspetterei l'unione per eliminare two, come è stato eliminato in other. Che cosa sto facendo di sbagliato?

risposta

6

Il problema qui è l'utilizzo di commit di squash.

Quando si esegue uno merge --squash, si abbandona tutta la cronologia di un ramo. Non hai davvero "fuso il ramo" - hai appena applicato una rappresentazione condensata della sua storia. Quindi, se lo fai più tardi merge --squash, git riapplicherà tutti i i commit nella cronologia del ramo (poiché i due rami non hanno antenato comune).

Quando si esegue il primo merge --squash, si crea un commit sul main che contiene "Crea uno, due e tre". Quindi la cronologia di main è prima "creare quattro", quindi "creare uno, due e tre".

Quando si esegue il secondo merge --squash, si aggiunge un commit composto da (in effetti) "Crea uno, due e tre" più "Rimuovi due". La rete di questi due commit insieme (schiacciato!) È "Crea uno e tre". Quindi git unisce automaticamente il commit "Crea uno e tre" con il tuo attuale stato repo, lasciandoti con quattro file presenti. L'unione dei contenuti ha esito positivo perché i file "uno" e "tre" sono identici su entrambi i lati.

È necessario utilizzare "reali" unioni o cherry-picking anziché lo schiacciamento se si desidera mantenere aggiornato un repository con un telecomando. Un merge --squash non è la stessa cosa di "riprodurre tutti i nuovi commit in un repository remoto e integrarli qui".

+0

È vero, questa spiegazione ha senso. Volevo fare una fusione di squash per non inquinare la storia di main con altri. Ma sembra che non ci sia altro modo. Grazie per l'aiuto! –

+1

@GergoErdosi Se si desidera * visualizzare * la cronologia "non inquinata", esaminare l'opzione 'first-parent' su' git log'. – Borealid

+0

Grazie per il suggerimento! –