(Questo è iniziato come una risposta a una domanda duplicata. Ho fatto un po 'di editing leggero per ripulirlo.)
Tutte le frecce interne di Git sono unidirezionali, rivolte all'indietro. Non esiste quindi una sintassi breve per spostarsi in avanti: semplicemente non è possibile.
E ' è possibile "muoversi contro le frecce", ma il modo per farlo è sorprendente se non avete visto prima, e poi evidente in seguito. Diciamo che abbiamo:
A <-B <-C <-D <-E <-- last
^
|
\--------- middle
L'utilizzo middle~2segue le frecce due volte da Cdietro a A. Quindi come ci spostiamo da Ca D? La risposta è: iniziamo da E, usando il nome last, e lavoriamo all'indietro fino a quando arriviamo middle, registrando i punti che visitiamo lungo la strada . Quindi ci spostiamo semplicemente nella direzione di last: muoviamo di un passo verso Do due verso E.
Ciò è particolarmente importante quando abbiamo filiali:
D--E <-- feature1
/
...--B--C <-- master
\
F--G <-- feature2
Quale commit è un passo dopo C? Non c'è una risposta corretta fino a quando non si aggiunge alla domanda: nella direzione di feature___ (riempire lo spazio vuoto).
Per elencare i commit tra C(escluso C) stesso e, diciamo, Gusiamo:
git rev-list --topo-order --ancestry-path master..feature2
Questo --topo-orderassicura che anche in presenza di complesse ramificazioni e fusioni, i commit escano in ordine topologicamente ordinato. Ciò è necessario solo se la catena non è lineare. Il --ancestry-pathvincolo significa che quando lavoriamo a ritroso da feature2, elenchiamo solo i commit che hanno commesso Ccome uno dei loro stessi antenati. Cioè, se il grafico, o comunque il relativo pezzo, in realtà assomiglia a questo:
A--B--C <-- master
\ \
\ F--G--J <-- feature2
\ /
H-------I <-- feature3
una semplice richiesta del modulo feature2..masterenumera commit J, Ge I, e Fe Hin un certo ordine. Con --ancestry-pathknock out He I: non sono discendenti di C, solo di A. Con --topo-orderci assicuriamo che l'attuale ordine di enumerazione sia J, quindi G, allora F.
Il git rev-listcomando distribuisce questi ID hash sull'output standard, uno per riga. Per avanzare di un passo nella direzione di feature2, quindi, vogliamo solo l' ultima riga.
È possibile (e allettante e può essere utile) aggiungere in --reversemodo da git rev-liststampare i commit in ordine inverso dopo averli generati. Questo funziona, ma se lo usi in una pipeline come questa:
git rev-list --topo-order --ancestry-path --reverse <id1>...<id2> | head -1
per ottenere il "prossimo commit nella direzione di id2", e c'è un elenco molto lungo di commit, il git rev-listcomando può ottenere una pipe spezzata quando tenta di scrivere su headcui ha smesso di leggere il suo input ed è uscito. Dal momento che gli errori di tubo rotto vengono normalmente ignorati dalla shell, questo funziona principalmente. Assicurati solo che siano ignorati nel tuo utilizzo.
È anche allettante aggiungere -n 1al git rev-listcomando, insieme a --reverse. Non farlo! Ciò si git rev-listinterrompe dopo aver fatto un passo indietro e quindi invertire l'elenco (una voce) di commit visitati. Quindi questo produce solo <id2>ogni volta.
Nota a margine importante
Si noti che con i frammenti del grafico "diamante" o "anello benzene":
I--J
/ \
...--H M--... <-- last
\ /
K--L
spostando una commettere "avanti" da Hdirezione lastsi arriva sia I o K . Non c'è niente che tu possa fare al riguardo: entrambi i commit sono un passo avanti! Se poi inizi dal commit risultante e fai un altro passo, ora sei impegnato in qualunque percorso tu abbia iniziato.
La cura per questo è di evitare di muoverti di un passo alla volta e rimanere bloccati in catene dipendenti dal percorso. Invece, se prevedi di visitare un'intera catena di percorsi degli antenati, prima di fare qualsiasi altra cosa , fai un elenco completo di tutti i commit nella catena:
git rev-list --topo-order --reverse --ancestry-path A..B > /tmp/list-of-commits
Quindi, visita ogni commit in questo elenco, uno alla volta, e otterrai l'intera catena. La --topo-orderfarà in modo di colpire I-e- Jin questo ordine, e K-e- Lin questo ordine (anche se non c'è un modo semplice per prevedere se si farà la coppia IJ prima o dopo la coppia KL).