2010-09-29 30 views
25

Estoy escribiendo un script que requiere verificar si un commit en particular es un commit/revert commit o no, y me pregunto si hay un truco git para eso.Indicando si un commit Git es un commit Merge/Revert

Lo que se me ocurrió hasta ahora (y definitivamente no quiero depender del mensaje de compromiso aquí) es marcar HASH^2 y ver si no aparece un error, ¿hay alguna otra manera mejor?

Respuesta

29

Averiguar si algo es una fusión es fácil. Eso es todo lo que se compromete con más de un padre. Para comprobar esto, se puede hacer, por ejemplo

$ git cat-file -p $commit_id 

Si hay más de una línea `padre' en la salida, que encontró una fusión.

Para revertir no es tan fácil. En general, las reversiones son solo confirmaciones normales que suceden para aplicar la diferencia de una confirmación previa en reversa, eliminando de manera efectiva los cambios que se han introducido. No hay nada especial de lo contrario.

Si se creó una reversión con git revert $commit, entonces git generalmente genera un mensaje de confirmación que indica la reversión y qué cometer revertido. Sin embargo, es posible revertir de otras formas, o simplemente cambiar el mensaje de confirmación de una confirmación generada por git revert.

En busca de los mensajes de revertir cometer generados ya podría ser una heurística lo suficientemente buena para lo que está tratando de lograr. Si no, tendrías que mirar a través de otras confirmaciones, comparar sus diferencias entre sí, buscar una es la operación inversa exacta de otra. Pero incluso esa no es una buena solución. A menudo, las reversiones suficientes son ligeramente diferentes a la inversa de la confirmación que están revocando, por ejemplo, para acomodar los cambios de código que ocurrieron entre la confirmación y la reversión.

+0

fijo que. ¡Gracias! – rafl

8

La respuesta usando git cat-file está usando un comando "fontanería", que generalmente es mejor para compilar scripts ya que es probable que el formato de salida no cambie. Los que usan git show y git rev-parse pueden necesitar cambiar con el tiempo ya que están usando los comandos porcelain.

La función fiesta He estado usando durante mucho tiempo utiliza git rev-list:

gitismerge() { 
    local sha="$1" 
    msha=$(git rev-list -1 --merges ${sha}~1..${sha}) 
    [ -z "$msha" ] && return 1 
    return 0 
} 

La lista de comandos porcelana/fontanería se pueden encontrar en la documentación para el comando de nivel superior git.

Este código utiliza git-rev-list con una consulta específica gitrevisions${sha}~1..${sha} de una manera que imprime segundo padre de un SHA si existe, o nada si no está presente, que es la definición exacta de una combinación de comprometerse.

Específicamente, SHA~1..SHA significa incluyen confirmaciones que son accesibles desde SHA, pero excluyen los que se puede llegar SHA ~ 1, que es el primer padre de SHA.

Los resultados se almacenan en $ msha y se prueban en vacío usando bash [ -z "$msha" ] fallando (devolviendo 1) si está vacío, o pasando (devolviendo 0) si no está vacío.

+0

¿Qué quieres decir con * porcelana *? ¿A qué respuesta te refieres exactamente? – knocte

+0

Hola @knocte He añadido algo de texto a mi respuesta con enlaces, HTH. – qneill

+0

gracias por la actualización; dos preguntas más: ¿qué hace '[-z foo]' en realidad? Quiero saber esto porque estoy interesado en usar esto, pero no en un script bash ... también, ¿cuáles son las desventajas y ventajas de su solución en comparación con el archivo 'cat-file'? ovaciones – knocte

2

Una manera de probar para una combinación de cometer:

$ test -z $(git rev-parse --verify $commit^2 2> /dev/null) || echo MERGE COMMIT 

En cuanto a git revert compromete, estoy de acuerdo con @rafl que el enfoque más realista es buscar el mensaje de texto modelo de reversión en el mensaje de confirmación; si alguien lo cambiara, detectarlo sería muy complicado.

+1

¿qué hace' test -z' exactamente? la pregunta no pide bashisms ... – knocte

+0

pruebas de vacío, consulte https://stackoverflow.com/questions/18096670/what-does-z-mean-in-bash – qneill

14

La siguiente instrucción arrojará solo los valores hash principales. Menos de filtrado necesaria ...

git show --no-patch --format="%P" <commit hash>

0

manera fácil de probar para cometer fusión:

git show --summary HEAD | grep -q ^Merge: 

Esto devolverá 0 para la fusión se compromete, 1 para no compromete fusión. Reemplace HEAD por la confirmación deseada para la prueba.

Ejemplo de uso:

if git show --summary some-branch | grep -q ^Merge: ; then 
    echo "some-branch is a merge" 
fi 
+1

esto me parece una solución bastante hacky , porque si alguien usa la palabra "Merge" en una confirmación normal (sin fusión), entonces tendría un ** falso positivo ** – knocte

+0

@knocte para eso es la carátula (^) en la expresión regular: busca para Merge _at the start of a line_. El mensaje de confirmación tiene una sangría de unos pocos espacios, por lo que incluso si contiene Merge, no coincidirá. Los contenidos de la propia dificultad (además de ser sangrados) no se muestran, cortesía de la bandera --summary. Sé que parece asqueroso, pero eso es Git :) esta solución no tiene falsos positivos. – hraban

+0

ok gracias por la aclaración; aún así, como dices, parece asqueroso ... – knocte