2012-04-16 12 views
20

Voglio trovare tutti i commit di unione che riguardano o riguardano un determinato file.L'unione di merge si ripercuote su un file

Per lo sfondo, qualcuno ha risolto male un conflitto durante l'unione e non è stato notato dal team per alcuni giorni. A quel punto, molte altre fusioni non correlate erano state commesse (alcuni di noi preferivano non usare rebase, o le cose sarebbero più semplici). Ho bisogno di localizzare il commit di "cattiva" unione, in modo che possa essere controllato per identificare cos'altro potrebbe essere stato ripristinato (e, ovviamente, per identificare e punire i colpevoli).

Lo scenario è simile a questo:

$ echo First > a.txt && git add a.txt && git commit -m 'First commit' 
$ git branch branch1 
$ echo "Second: main-branch" >> a.txt && git commit -a -m 'Commit on master' 
$ git tag a1 
$ echo "Third: main" >> a.txt && git commit -a -m 'Other commit on master' 
$ git checkout branch1 
$ echo "Second: on branch1" >> a.txt && git commit -a -m 'Commit on branch' 
$ git tag b1 

... Così ora ci sono modifiche in conflitto a a.txt in master e Branch1.

$ git checkout master 
$ git merge branch1 
Auto-merging a.txt 
CONFLICT (content): Merge conflict in a.txt 
Automatic merge failed; fix conflicts and then commit the result. 
$ cat a.txt 
First 
<<<<<<< HEAD:a.txt 
Second: main-branch 
Third: main 
======= 
Second: on branch1 
>>>>>>> branch1:a.txt 
$ vi a.txt 
# ... 
$ cat a.txt 
First 
Second: on branch1 
$ git add a.txt 
$ git commit -m 'Merge commit' 

... In altre parole, la risoluzione è "prendere loro". Il grafico ora si presenta così:

$ git log --graph --branches --format='%h %s %d' 
* fefb623 Merge commit (refs/heads/master) 
|\ 
| * 93e065e Commit on branch (refs/tags/b1, refs/heads/branch1) 
* | cf4d12b Other commit on master 
* | 6fade67 Commit on master (refs/tags/a1) 
|/ 
* 07545ea First commit 

A questo punto la versione errata di a.txt è sul master. La versione di a1 è ciò che vogliamo, ma è stata commessa la versione b1. Finora ho provato:

$ git log --decorate --oneline a.txt 
93e065e (refs/tags/b1, refs/heads/branch1) Commit on branch 
07545ea First commit 

Ok, quindi non vengono visualizzati né a1 né il commit di unione.

$ git log --decorate --oneline --follow a.txt 
... 

Questo mi mostra tutto su entrambi i rami, ma continua a non commettere l'unione.

$ git log --oneline --graph --decorate a1..master 
... 

Questo è, naturalmente, "tutto in master non in A1", che opera in questo esempio giocattolo, ma nel mio caso reale mi dà tutte le unioni fatto di recente (e nessuna indicazione di cui uno ha toccato a.txt) .

Riesco a razionalizzare la scomparsa di a1 dalla cronologia del file, poiché l'unione ha scelto di omettere quel cambiamento (almeno nel senso in cui si preoccupa, penso). Ma come faccio a localizzare tutti i commit di unione che riguardano a.txt? È possibile anche senza l'ispezione manuale di tutte le fusioni di unione di candite?

+0

Il commettere registro non mostrano fonde perché diff con il primo genitore commit, che è nel ramo si Unite da; quindi git ritiene che nessun file sia stato modificato – CharlesB

risposta

21

Il problema nel tuo caso è che i commit di unione sono vuoti, perché si prendono roba solo da un ramo, quindi git semplifica la cronologia rimuovendo quei commit "vuoti".

Quindi, per visualizzare le conferme di fusione nel registro, è necessario comunicare a git di modificare la semplificazione della cronologia, dicendo --simplify-merges. Se vuoi capire perché devi usare questo, vai avanti nella pagina man git log, ma io sono fuori di esso :) Comunque in questo caso il commit di unione viene mostrato correttamente con il filtro a.txt, quindi è quello che vuoi .

Infine, si desidera mostrare diff due volte, con ciascun genitore, con -m.

Quindi questo dà

git log -U -m --simplify-merges --merges -- a.txt 

con uscita

commit a7340d6e91deedff6f52c8ec8da932245f73e5f6 (from d577e6c4dcbff5485ded666c89f38 
Merge: d577e6c fe3c4d2 

    merge commit 

diff --git a/a.txt b/a.txt 
index 319137b..1aa6dc4 100644 
--- a/a.txt 
+++ b/a.txt 
@@ -1,3 +1,2 @@ 
First 
-Second: main-branch 
-Third: main 
+Second: on branch1 
+0

Sì, è il differenziale che stavo cercando. –

+0

+1 per --simplify-merges. Non vedere la fusione si impegna - o rendersi conto che sono nascosti dal log - ore sprecate del mio tempo oggi. – staafl

2

È possibile aggiungere --merges al comando di registro. Questo elencherà solo i commit di unione. Inoltre, è possibile specificare --first-parent in modo da seguire solo la cronologia del ramo e non considerare la cronologia dei rami incorporati.

+0

questo non funzionerà perché 'git log a.txt' non elenca il merge commit (non so perché) – CharlesB

+0

Probabilmente solo se hai risolto i conflitti nel commit di merge che coinvolgono quel file ... che ne dici di 'git log - a.txt'? –

+0

no, non viene visualizzato, anche se il conflitto di merge riguarda 'a.txt'; se risolvi il conflitto di unione selezionando solo le modifiche dalla loro, commit diff è vuoto ed è nascosto dal log. Tuttavia ho trovato come aggirare – CharlesB