Con Git, come posso sapere se un commit nel mio ramo è un discendente di un altro commit?
--is-ancestor
soluzione.
Con Git, come posso sapere se un commit nel mio ramo è un discendente di un altro commit?
--is-ancestor
soluzione.
Risposte:
Se si desidera verificarlo a livello di codice (ad es. Nello script), è possibile verificare se git merge-base A B
è uguale a git rev-parse --verify A
(quindi A è raggiungibile da B) o se lo è git rev-parse --verify B
(quindi B è raggiungibile da A). git rev-parse
è qui necessario per convertire dal nome del commit in commit SHA-1 / commit id.
È anche possibile usare git rev-list
come nella risposta VonC .
Modifica: in Git moderno esiste un supporto esplicito per questa query sotto forma di git merge-base --is-ancestor
.
Se uno dei commit di cui stai chiedendo è un suggerimento di filiale , allora git branch --contains <commit>
o git branch --merged <commit>
potrebbe essere una soluzione non programmatica migliore.
git checkout -b quickcheck <more-recent-commit-ID>
e poi git branch --contains <older-commit-ID>
(e quindi git branch -D quickcheck
sbarazzarsi del ramo temporaneo).
git merge-base --is-ancestor
di 2 anni.
git branch --contains <commit>
e git merge-base --is-ancestor ...
: 3m40s vs 0.14s
Da Git 1.8.0, questo è supportato come opzione per merge-base
:
git merge-base --is-ancestor <maybe-ancestor-commit> <descendant-commit>
Dalla pagina man:
--is-antenato
Controllare se il primo è un antenato del secondo e uscire con lo stato 0 se vero, o con lo stato 1 in caso contrario. Gli errori sono segnalati da uno stato diverso da zero che non è 1.
Per esempio:
git merge-base --is-ancestor origin/master master; echo $?
git merge-base THING --is-ancestor OF_THING && echo yes || echo no
ad es .:git merge-base my-feature-branch --is-ancestor master && echo yes || echo no
git merge-base --is-ancestor -- commit commit
lavora per gli hash al mio fianco con git
2.1.4 (Debian / Devuan 7.10 jessie) e 1.9.1 (Ubuntu 14.04 fidato) che ora sono piuttosto antichi. Funziona anche con Debian wheezy, se lo fai sudo apt-get install git/wheezy-backports
.
Questo tipo di operazioni si basa sulla nozione di intervallo di revisioni dettagliato nella domanda SO: " Differenza in 'git log origin / master' rispetto a 'git log origin / master ..' ".
git rev-list
dovrebbe essere in grado di tornare indietro da un commit, fino a un altro se raggiungibile.
Quindi proverei:
git rev-list --boundary 85e54e2408..0815fcf18a
0815fcf18a19441c1c26fc3495c4047cf59a06b9
8a1658147a460a0230fb1990f0bc61130ab624b2
-85e54e240836e6efb46978e4a1780f0b45516b20
(I commit al confine sono preceduti da -
)
Se l'ultimo commit visualizzato è uguale al primo commit nel git rev-list
comando, allora è un commit raggiungibile dal secondo commit.
Se il primo commit non è raggiungibile dal secondo, non git rev-list
dovrebbe restituire nulla.
git rev-list --boundary A..B
finirebbe A
, se A
è raggiungibile da B
.
È lo stesso di:
git rev-list --boundary B --not A
, con B
un riferimento positivo e A
un riferimento negativo .
Inizierà a B
e tornerà indietro nel grafico fino a quando non incontra una revisione raggiungibile da A
.
Direi che se A
è direttamente raggiungibile B
, incontrerà (e visualizzerà, a causa --boundary
dell'opzione) A
stessa.
-85e54e2...
lo snippet ha un segno meno? anche un possibile errore di battitura: "... è lo stesso del primo commit ..."
-
significa che è un commit di confine. Ho modificato la risposta per renderlo più chiaro, nonché per aggiornare i collegamenti ai documenti e correggere l'errore di battitura per questa risposta di 5 anni.
Un altro modo sarebbe usare git log
e grep
.
git log --pretty=format:%H abc123 | grep def456
Questo produrrà una riga di output se commit def456 è un antenato di commit abc123 o altrimenti nessun output.
Di solito puoi --pretty
evitare di omettere l' argomento, ma è necessario se vuoi assicurarti di cercare solo tra gli hash di commit effettivi e non attraverso i commenti del registro e così via.
--pretty
usare --oneline: git log --oneline ce2ee3d | grep ec219cc
funziona benissimo
https://stackoverflow.com/a/13526591/895245 lo menziona, ora per renderlo più amico dell'uomo:
git-is-ancestor() (
if git merge-base --is-ancestor "$1" "$2"; then
echo 'ancestor'
elif git merge-base --is-ancestor "$2" "$1"; then
echo 'descendant'
else
echo 'unrelated'
fi
)
alias giia='git-is-ancestor'
git show-branch branch-sha1 commit-sha1
Dove:
Se stai usando git merge-base --is-ancestor
, assicurati di usare Git 2.28 (Q3 2020)
Con Git 2.28 (3 ° trimestre 2020), alcuni campi in " struct commit
" che non devono essere sempre presenti sono stati spostati per il commit delle lastre.
Vedi commit c752ad0 , commit c49c82a , commit 4844812 , commit 6da43d9 (17 giu 2020) di Abhishek Kumar ( abhishekkumar2718
) .
(Unita da Junio C Hamano - gitster
- in commit d80bea4 , 06 lug 2020)
commit-graph
: introdurrecommit_graph_data_slab
Firmato-fuori-da: Abhishek Kumar
Il commit di struct viene utilizzato in molti contesti. Tuttavia, i membri
generation
egraph_pos
vengono utilizzati solo per operazioni correlate al commit-graph e altrimenti sprecano memoria.Questo spreco sarebbe stato più pronunciato mentre passavamo al numero di generazione v2, che utilizza il numero di generazione a 64 bit anziché gli attuali 32 bit.
Poiché sono spesso accessibili insieme, introduciamo struct
commit_graph_data
e spostiamoli su unacommit_graph_data
lastra.Mentre la suite di test generale funziona altrettanto velocemente
master
, (serie: 26m48s,:master
27m34s, più veloce del 2,87%), alcuni comandi come quelligit merge-base --is-ancestor
sono stati rallentati del 40% come scoperto da Szeder Gábor .
Dopo aver ridotto al minimo l'accesso al commit-slab, il rallentamento persiste ma si avvicina al 20%.Derrick Stolee ritiene che il rallentamento sia attribuibile all'algoritmo sottostante piuttosto che alla lentezza dell'accesso al commit-slab e che seguiremo in una serie successiva.
Sulla base della risposta di itub, nel caso in cui sia necessario eseguire questa operazione per tutti i tag nel repository:
for i in `git tag` ; do echo -ne $i "\t" ; git log --pretty=format:%H $i | (grep <commit to find> || echo ""); done