Git: trova il più recente antenato comune di due rami


844

Come trovare l'antenato comune più recente di due rami Git?


3
Definisci i più recenti: tempo del mondo reale, numero di commit, altre metriche?
Ciro Santilli 17 冠状 病 六四 事件 法轮功

2
Rilevanti (unioni criss-cross): stackoverflow.com/questions/26370185/...
jub0bs

1
@CiroSantilli 新疆 改造 中心 996ICU 六四 事件 è lo stesso in qualsiasi metrica, no?
YakovL

@YakovL Credo di no a causa della ramificazione e perché è possibile impostare date di commit arbitrarie sui propri oggetti di commit: quella data stessa probabilmente non è quella che si desidera.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

1
@CiroSantilli 新疆 改造 中心 996ICU 六四 事件 mi sembra che possa essere diverso solo se prima dell'ultimo commit comune nella struttura c'è un commit che ha un timestamp più vecchio. Puoi fornire un esempio meno banale?
YakovL

Risposte:


1019

Stai cercando git merge-base. Uso:

$ git merge-base branch2 branch3
050dc022f3a65bdc78d97e2b1ac9b595a924c3f2

85
Nota che questo trova l'ultimo antenato comune ... che credo sia quello che vuole l'interrogante, quindi +1. Basta notare che, nel caso in cui qualcuno viene qui a cercare di trovare il più antico antenato comune (come ho fatto io) - per il quale, vedi anche: stackoverflow.com/questions/1527234/...
Lindes

16
@funroll: O la scorciatoia per questo:git log master...HEAD
CB Bailey

17
@lindes il più antico antenato comune non sarebbe il commit iniziale?
Thorbjørn Ravn Andersen,

8
@ ThorbjørnRavnAndersen, sì, suppongo che sia così ... La difficoltà nella descrizione deriva dal fatto che git usa un grafico aciclico diretto, eppure è spesso pensato come un albero, che tecnicamente non lo è. Per essere più attento nella mia formulazione, stavo parlando del caso in cui si desidera divergere il genitore della prima istanza dei "rami" ... poiché potrebbero avere più punti in cui si sono ricongiunti e suddivisi, questo è il "più vecchio" di questi, ma non è veramente il più antico antenato, che è (credo) sempre il commit iniziale.
termina il

5
Mentre questa domanda riguarda strettamente la ricerca di un antenato comune di due rami, chiunque desideri l'antenato comune di tre o più rami dovrebbe notare che è necessario passare la --octopusbandiera per ottenere il risultato giusto. L'ovvio ma sbagliato git merge-base branch1 branch2 branch3ti darà un impegno, ma, come descritto nella sezione Discussione nei documenti, non è necessariamente un antenato comune di tutti e tre i rami.
Mark Amery,

46

git diff master...feature

mostra tutti i nuovi commit del ramo della funzione corrente (possibilmente multi-commit).

man git-diff documenti che:

git diff A...B

equivale a:

git diff $(git merge-base A B) B

ma ...è più facile da scrivere e ricordare.

Come menzionato da Dave , il caso speciale di HEADpuò essere omesso. Così:

git diff master...HEAD

equivale a:

git diff master...

che è sufficiente se il ramo corrente è feature.

Infine, ricorda che l'ordine conta! In questo modo git diff feature...masterverranno visualizzate le modifiche che non sono masterattive feature.

Vorrei che più comandi git supportassero quella sintassi, ma non credo che lo facciano. E alcuni hanno anche una semantica diversa per ...: quali sono le differenze tra il punto doppio ".." e il punto triplo "..." negli intervalli di commit di Git?


8
O solo git diff master...nel caso speciale di diffing toHEAD
Dave,

il "..." non ha funzionato per me in PowerShell, divertente ha funzionato nella console git forse il repository non era completo, git diff $ (git merge-base AB) B ha funzionato e dato che sono un po 'nuovo con git Ero un po 'scettico sul fatto che questo potesse fondere i rami :)
Moiz Ahmed,

1
Wow. abbastanza sorprendente. e se il ramo che desideri non esiste nel tuo repository locale perché non l'hai mai verificato, puoi semplicemente farlogit diff origin/branchname...
Mark Ch

25

Come indicato in una risposta precedente, git merge-basefunziona:

$ git merge-base myfeature develop
050dc022f3a65bdc78d97e2b1ac9b595a924c3f2

ma se myfeatureè il ramo corrente, come è comune, puoi usare use --fork-point:

$ git merge-base --fork-point develop
050dc022f3a65bdc78d97e2b1ac9b595a924c3f2

Questo argomento funziona solo con versioni sufficientemente recenti di git. Purtroppo non sempre funziona, tuttavia, e non è chiaro il perché. Si prega di fare riferimento alle limitazioni annotate verso la fine di questa risposta .


Per informazioni complete sul commit, considerare:

$ git log -1 $(git merge-base --fork-point develop) 

Io ho git version 2.14.1.windows.1. Correre git merge-base --fork-point branch2con un ramo (con i propri commit) che so che ha biforcuto dal ramo corrente non produce alcun risultato, mentre git merge-base branch1 branch2mostra correttamente il punto di fork. Quale potrebbe essere il problema?
ADTC

@ADTC Acquista branch2ed esegui git merge-base --fork-point branch1.
Acumenus,

@ADTC Usa un visualizzatore di commit grafico, ad es gitk. Ecc. Per vedere come appare l'albero. Forse otterrai la tua risposta.
Acumenus,

Non vedo nulla di strano sull'albero mentre lo vedo graficamente. Posso tracciare i percorsi e trovare l'antenato comune che corrisponde al risultato di git merge-base branch1 branch2. Ma la cosa strana è che --fork-pointnon dà nulla in entrambi i modi. Hai confermato che funziona per te come previsto?
ADTC,

1
Ottengo lo stesso che @ADTC. Il comando 'git log -1 $ (git merge-base --fork-point anotherBranch)' non mostra alcun risultato usando la versione 2.16.2.windows.1 di git.
Masinger,

10

Con gitkpuoi visualizzare graficamente i due rami:

gitk branch1 branch2

E poi è facile trovare l'antenato comune nella storia dei due rami.


6
Non tutto può essere fatto visivamente in ogni caso. Ci sono ragioni per cui potrebbe essere necessario automatizzare le cose a livello di codice.
ADTC
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.