Git est un DAG d'instantanés, chaque nœud du graphique représentant un commit. Chaque validation peut avoir des validations parentales 'n'.
Étant donné deux commits, existe-t-il un moyen unique et concis de discerner "l'ordre" de ces deux dans le DAG. git rev-list
semble être le plus prometteur, mais je n'arrive pas à trouver la bonne incantation.
Idéalement, j'aurais quelque chose comme ceci
$ git related hash1 hash2
hash1 is ancestor of hash2
OR
hash2 is ancestor of hash1
OR
hash1 unrelated to hash2
OR
hash1 is equal to hash2
git merge-base --is-ancestor <commit1> <commit2>
Il existe plusieurs façons de trouver la réponse à cette question. Le plus simple est d'utiliser
git merge-base --is-ancestor <commit> <commit>
De la documentation de git merge-base
:
--is-ancestor
Vérifiez si le premier
<commit>
est un ancêtre du second<commit>
, et quittez avec l'état 0 si vrai, ou avec l'état 1 sinon. Les erreurs sont signalées par un état différent de zéro différent de 1.
...
notationUne autre option consiste à utiliser git log
et utilisez la notation à trois points ...
pour dire à Git de sortir l'union définie des validations enfants, moins l'intersection définie. Fondamentalement, il vous indique comment un ensemble de validations a divergé les uns des autres:
$ git log --oneline --graph --left-right \
--first-parent --decorate <commit1>...<commit2>
La commande ci-dessus vous montrera les validations accessibles depuis commit1
ou commit2
, mais pas les deux, c'est-à-dire C1 UNION C2 - C1 INTERSECTION C2, en termes d'opérations définies.
Si aucun commit n'est parent de l'autre, vous verrez les commits enfants des deux, mais si l'un est un ancêtre de l'autre, vous ne verrez que la sortie du commit descendant, car l'ancêtre est contenu dans le chemin du descendant, et est donc exclu de la sortie.
Vous pouvez en savoir plus sur git log
et notation à trois points à partir des ressources suivantes:
git-rev-list (1) semble pouvoir être utilisé pour y répondre. Une autre façon consiste à simplement attacher des étiquettes de branche temporaires aux validations que vous souhaitez tester, puis à utiliser le --contains
option pour git branch
:
git branch --contains <commit-to-test>
La sortie sera toutes les branches qui contiennent le commit quelque part dans leur arbre de commit, donc en utilisant une branche temporaire sur l'autre commit, vous pouvez voir si le commit que vous testez est un ancêtre.
De la documentation:
--contains [<commit>]
Liste uniquement les branches qui contiennent le commit spécifié (HEAD si non spécifié).
Le script Shell suivant pourrait faire l'affaire:
if git rev-list $SHA1 | grep -q $SHA2 ; then echo "$SHA2 is ancestor of $SHA1"
Elif git rev-list $SHA2 | grep -q $SHA1 ; then echo "$SHA1 is ancestor of $SHA2"
else echo "$SHA1 unrelated to $SHA2" ; fi
Ou, pour bien l'envelopper dans un alias git:
git config --global alias.related '!function git_related() { if git rev-list $1 | grep -q $2 ; then echo "$2 is ancestor of $1" ; Elif git rev-list $2 | grep -q $1 ; then echo "$1 is ancestor of $2" ; else echo "$1 unrelated to $2" ; fi } ; git_related $1 $2'
if (( $(git rev-list $1..$2|wc -l) == 0 )); then echo "$2 is ancestor of $1"
Elif (( $(git rev-list $2..$1|wc -l) == 0 )); then echo "$1 is ancestor of $2"
else echo "$1 and $2 are unrelated"
fi
git log --oneline -1 OLD_SHA..NEW_SHA
Si cela vous donne un journal, OLD_SHA est le parent de NEW_SHA.
Pour s'appuyer sur l'excellent _ helmbert git related
alias, voici une version qui accepte également les noms de branche (ou HEAD etc) comme arguments, plutôt que de simplement valider les identifiants:
git config --global alias.related '!function git_related() { commit1=`git log -n 1 --format="%h" $1` ; commit2=`git log -n 1 --format="%h" $2` ; if git rev-list $commit1 | grep -q $commit2 ; then echo "$2 is ancestor of $1" ; Elif git rev-list $commit2 | grep -q $commit1 ; then echo "$1 is ancestor of $2" ; else echo "$1 unrelated to $2" ; fi } ; git_related $1 $2'