Dado un id de confirmación, ¿cómo determinar si la rama actual contiene la confirmación?

156

Lo que intento hacer es una verificación de versión. Quiero asegurarme de que el código se mantenga por encima de una versión mínima. Entonces, necesito una manera de saber si la rama actual contiene una confirmación específica.

TieDad
fuente
10
Consulte el duplicado propuesto para saber cómo encontrar todas las ramas que contienen una confirmación específica. Para averiguar si la rama actual contiene commit C , use el comando "plomería" git merge-base --is-ancestor. La rama actual contiene C si C es un antepasado de HEAD, entonces:if git merge-base --is-ancestor $hash HEAD; then echo I contain commit $hash; else echo I do not contain commit $hash; fi
torek
1
Hola, envíe esto como respuesta para que pueda seleccionarse como la respuesta correcta =)
Ben
1
@Ben: lo agregué como una respuesta wiki comunitaria.
Zitrax
1
@Remover: en los scripts de shell, cero es verdadero, no cero es falso: lo contrario de la convención C. /bin/truefue implementado originalmente como exit 0y /bin/falsecomo exit 1. (Conchas modernos entonces se han construido en.)
torek

Respuestas:

220

Hay múltiples formas de lograr este resultado. La primera opción ingenua es usar git logy buscar un commit específico usando grep, pero eso no siempre es preciso

git log | grep <commit_id>

Usted es mejor usar git branchdirectamente para encontrar todas las ramas que contienen dado COMMIT_IDel uso

git branch --contains $COMMIT_ID

El siguiente paso es descubrir la rama actual que se puede hacer desde git 1.8.1usar

git symbolic-ref --short HEAD

Y combinados juntos como

git branch $(git symbolic-ref --short HEAD) --contains $COMMIT_ID

Pero el comando anterior no devuelve verdadero o falso y hay una versión más corta que devuelve el código de salida 0 si commit está en la rama actual O el código de salida 1 si no

git merge-base --is-ancestor $COMMIT_ID HEAD

El código de salida es bueno, pero como desea una cadena trueo falsecomo respuesta, debe agregar un poco más y luego combinarlo con ifbash obtendrá

if [ 0 -eq $(git merge-base --is-ancestor $COMMIT_ID HEAD) ]; then echo "true"; else echo "false"; fi
JiriS
fuente
9
Eso no es correcto; esto greppodría dar lugar a falsos positivos si git logmenciona el SHA de confirmación por otros motivos, por ejemplo, se menciona en un mensaje de confirmación como resultado de un puerto de otra rama.
Adam Spires
1
Corregido (o más bien agregado otra opción).
JiriS
3
Consulte el comentario sobre la pregunta, que utiliza el conjunto de herramientas de git incorporado. stackoverflow.com/questions/43535132/…
Ben
2
Me gusta la primera opción, pero para descartar la objeción de Adam, agregaría la opción --format=format:%Ha git log.
PJSCopeland
71

Obtenga una lista de sucursales que contiene la confirmación específica.

# get all the branches where the commit exists
$ git branch --contains <commit-id>

Compruebe si una rama tiene el compromiso específico.

# output the branch-name if the commit exists in that branch
$ git branch --contains <commit-id> | grep <branch-name>

Busque en la rama (digamos feature) con coincidencia exacta .

$ git branch --contains <commit-id> | grep -E '(^|\s)feature$'

por ejemplo, si usted tiene 3 sucursales locales llaman feature, feature1, feature2a continuación,

$ git branch --contains <commit-id> | grep 'feature'

# output
feature
feature1
feature2

$ git branch --contains <commit-id> | grep -E '(^|\s)feature$'

# output
feature     

También puede buscar en ambas localy remoteramas (uso -a) o solo en remoteramas (uso -r).

# search in both 'local' & 'remote' branches  
$ git branch -a --contains <commit-id> | grep -E '(^|\s)feature$'

# search in 'remote' branches  
$ git branch -r --contains <commit-id> | grep -E '(^|\s)feature$'
Sajib Khan
fuente
1
El grepaquí también podría dar lugar a falsos positivos si hay otras ramificaciones que contienen el envío de datos cuyos nombres contienen también <branch-name>como una subcadena.
Adam Spires
1
Sí @AdamSpiers, Actualicé la respuesta con coincidencia exacta con el nombre de la sucursal porgrep -E '(^|\s)branchname$'
Sajib Khan
1
Según este comentario sobre la pregunta relacionada , puede ser útil agregar la opción -r("remoto") o -a("todo") git branchpara buscar ramas que no se puedan replicar en el clon de repositorio local.
sxc731
Esto no funcionó para mí, lo necesitaba git branch --all --contains <commit-id>
Arthur Tacca
7

Comentario extraído por @torek como respuesta:

Consulte el duplicado propuesto para saber cómo encontrar todas las ramas que contienen una confirmación específica.

Para averiguar si la rama actual contiene commit C, use el comando "plomería" git merge-base --is-ancestor. La rama actual contiene C si C es un ancestro de HEAD, entonces:

if git merge-base --is-ancestor $hash HEAD; then
    echo I contain commit $hash
else
    echo I do not contain commit $hash
fi

(Nota al margen: en los scripts de shell, un comando que sale de cero es "verdadero", mientras que uno que sale de cero es "falso").

torek
fuente
4

Para enumerar sucursales locales que contienen commit:

git branch --contains <commit-id>

y para enumerar todas las ramas, incluidas las remotas, que contienen commit:

git branch -a --contains <commit-id>

De manera similar para verificar si commit es en particular una rama:

git log <branch> | grep <commit_id>

y si la rama no existe localmente el prefijo nombre de rama con origin/

hgrey
fuente
Votado por el comentario sobre -a. Gracias por ese consejo!
Thorkil Værge
3

Sí, otra alternativa:

git rev-list <branch name> | grep `git rev-parse <commit>`

Esto funciona mejor para mí, ya que también funcionaría en ramas remotas almacenadas en caché local, como remotes/origin/master, en las que git branch --containsno funcionará.

Esto cubre más que la pregunta de OP sobre la "rama actual", pero me parece tonto pedir una versión de "cualquier rama" de esta pregunta, así que decido publicar aquí de todos modos.

Logicor
fuente
1
git branch --contains <commit-id> --points-at <target branch name>

Devolverá el nombre de la rama de destino si la identificación de confirmación existe en esa rama. De lo contrario, el comando fallará.

Sueño
fuente
no ...error: malformed object name 'branch-name'
bbodenmiller
1
Es posible que obtenga ese error en 2 casos 1. Cuando el <nombre de rama> dado no contiene el <commit id> 2. La comprobación <nombre de rama> no es el <nombre de rama>
dado
0

Como esta pregunta tiene algunas buenas respuestas con guión, estoy agregando mis favoritos.

Este le mostrará, para los últimos $ncommits en $brqué ramas contiene cada uno:

br=mybranch
n=10
git log --oneline -n$n $br | awk '{print; system("git branch --contains "$1)}'

Este es similar pero hace lo mismo para una lista de ramas:

br="mybranch yourbranch herbranch"
n=4
for br in $brs; do git log --oneline -n$n $br | awk '{print; system("git branch --contains "$1)}'; done
Bruno Bronosky
fuente