git - tag - ¿Cómo puedo saber si un commit es un antepasado de otro commit(o viceversa)?
git tag remove (5)
Git es un DAG de instantáneas, con cada nodo en el gráfico que representa un compromiso. Cada confirmación puede tener ''n'' confirmaciones principales.
Dado cualquiera de los dos compromisos, ¿hay una manera única y concisa de discernir el "orden" de estos dos en el DAG? git rev-list
parece ser el más prometedor, pero parece que no puedo encontrar el conjuro correcto.
Idealmente, tendría algo como lo siguiente
$ git related hash1 hash2
hash1 is ancestor of hash2
O
hash2 is ancestor of hash1
O
hash1 unrelated to hash2
O
hash1 is equal to hash2
Utilice git merge-base --is-ancestor <commit1> <commit2>
Hay más de una manera de encontrar la respuesta a esto. Lo más sencillo es utilizar.
git merge-base --is-ancestor <commit> <commit>
De la documentación para git merge-base
:
--is-ancestor
Compruebe si el primer
<commit>
es un antepasado del segundo<commit>
, y salga con el estado 0 si es verdadero, o con el estado 1 si no lo es. Los errores se señalan con un estado distinto de cero que no es 1.
Otras opciones
log git con triple punto ...
notación
Otra opción es usar el git log
y usar la notación de puntos triples ...
para decirle a Git que genere la unión establecida de los compromisos secundarios, menos la intersección establecida. Básicamente, te dice cómo un conjunto de confirmaciones se han separado entre sí:
$ git log --oneline --graph --left-right /
--first-parent --decorate <commit1>...<commit2>
El comando anterior le mostrará las confirmaciones accesibles desde commit1
o commit2
, pero no ambas, es decir, C1 UNION C2 - C1 INTERSECCIÓN C2, en términos de operaciones de conjunto.
Si ninguna de las confirmaciones es un padre de la otra, verá las confirmaciones secundarias de ambas, pero si una es un antecesor de la otra, solo verá la salida de la confirmación descendiente, ya que la antecesora está contenida en la ruta del descendiente, y por lo tanto se excluye de la salida.
Puede leer más sobre el git log
y la notación de puntos triples en los siguientes recursos:
rama de git - contiene opción
git-rev-list(1) parece que podría usarse para responder a esto. Otra forma es simplemente adjuntar etiquetas de sucursal temporales a las confirmaciones que desea probar, y luego usar la opción --contains
para git branch
:
git branch --contains <commit-to-test>
La salida será todas las ramas que contengan la confirmación en algún lugar de su árbol de confirmación, por lo que al usar una rama temporal en la otra confirmación, puede ver si la confirmación que está probando es un antepasado.
De la documentación:
--contains [<commit>]
Solo enumere las ramas que contienen la confirmación especificada (HEAD si no se especifica).
El siguiente script de shell podría hacer el truco:
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
O, para envolverlo cuidadosamente en un alias de 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''
Para desarrollar el excelente alias git related
@ helmbert, aquí hay una versión que también acepta nombres de rama (o HEAD, etc.) como argumentos, en lugar de solo cometer ID:
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''
git log --oneline -1 OLD_SHA..NEW_SHA
Si esto te da un registro, entonces OLD_SHA es el padre de NEW_SHA.
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