2010-03-14 20 views
33

Antecedentes: utilizo un sistema de compilación automatizado que toma un hash git como entrada, así como también el nombre de la rama en la que existe el hash, y lo construye. Sin embargo, el sistema de compilación usa solo el hash para verificar el código y compilarlo; simplemente almacena el nombre de la rama, tal como figura en los metadatos de la base de datos de compilación.¿Cómo puedo determinar si existe un hash git dado en una rama determinada?

Me preocupa que los desarrolladores proporcionen accidentalmente un nombre de rama incorrecto cuando inician una construcción, causando confusión cuando las personas miran el historial de compilación.

Entonces, ¿cómo puedo confirmar, antes de pasar el hash y el nombre de la rama al sistema de compilación, que el hash dado en realidad proviene de la rama dada?

+3

¿Por qué necesita el nombre de la sucursal? parece una información extra inútil para el sistema de compilación. Y realmente no veo cómo sería útil para un desarrollador leer los registros de compilación. – hasen

+0

podría necesitar el nombre de la sucursal en caso de que su flujo de trabajo ha, no sé, una rama desarrollar y maestro utilizado para el despliegue y desea saber si comete metido en ninguna en particular? Por cierto, acepte la respuesta real. –

+0

@Pinko creo que la respuesta seleccionada debe ser [éste] (https://stackoverflow.com/a/2444924/161278). Dado que tiene muchos más votos y es mucho más simple debido al uso de la funcionalidad nativa de git. –

Respuesta

10

Hmm, este uso de un nombre de rama parece a pescado. Como en la respuesta de Dustin, puede haber múltiples ramas que contengan un compromiso. ¿Por qué uno de esos nombres de rama es mejor que otro para este propósito?


Si solo le importa una rama específica, puede calcular la "base de combinación" entre la bifurcación y la confirmación.

En los siguientes diagramas, la confirmación de compilación es C, la punta de la rama reclamada es T, y la base de combinación está etiquetada con M encima.

  • Si M igual a igual CT, a continuación, el de la confirmación de construir es la punta de la rama se reivindica.

       M 
           ↓ 
    o--o--o--o--o--x branch # x is both C and T 
    
  • Si M es igual a C, a continuación, la punta de la rama reivindicada es un descendiente del comprometan a construir.

     M 
         ↓ 
    o--o--C--o--o--T branch 
    
  • Si M es igual a T, entonces el comprometen a construir es un descendiente de la punta de la rama se reivindica.

     M 
         ↓ 
    o--o--T   branch 
         \ 
         o--o--C 
    
  • Si M es igual a otra cosa, entonces C es un descendiente de un antepasado de T.

     M 
         ↓ 
    o--o--o--o--o--T branch 
         \ 
         o--o--C 
    
  • Si no hay M, entonces el comprometen a construir no se relaciona con la rama reivindica.

    o--o--o--o--o--T branch 
    
    o--o--o--o--C 
    

usted puede hacer esta verificación como esto:

#!/bin/sh 

# Usage: is-ancestor-of <branch> <commit> 

if test $# -ne 2; then 
    echo "$0"': invalid arguments' 
    exit 128 
fi 
claimed_branch="$1" 
commit="$2" 

merge_base="$(git merge-base "$commit" "$claimed_branch")" && 
    test -n "$merge_base" && 
    test "$merge_base" = "$(git rev-parse --verify "$commit")" && 
    exit 0 

echo "$commit is not an ancestor of $claimed_branch" 1>&2 
exit 1 

El script anterior en realidad no requieren o comprobar que el argumento 'rama' es una rama (que podría ser cualquier compromiso ish). Para comprobar que algo es en realidad una rama, se usa algo como esto:

#!/bin/sh 

# Usage: is-branch <branch> 

if test $# -ne 1; then 
    echo "$0"': invalid arguments' 
    exit 128 
fi 
branch="$1" 

# check various branch hierarchies, adjust as needed 
git show-ref --verify refs/heads/"$branch" || 
git show-ref --verify refs/remotes/"$branch" || { 
    echo "not a branch name: $branch" 1>&2 
    exit 1 
} 

por lo que podría usarlas juntas para comprobar que algo es una rama y que un cierto revisiones existentes en esa rama:

is-branch "$claimed_branch" && is-ancestor-of "$claimed_branch" "$commit_to_build" 
+0

Muy interesante. 1 – VonC

+2

más simple solución @ http://stackoverflow.com/a/2444924/292408 –

+6

Por qué diablos tendría que hacer esto cuando Git tiene una mejor solución integrada? ¿Por qué demonios se aceptó esta respuesta ridículamente complicada cuando claramente no es la mejor? Perdí el tiempo revisando esto en lugar de desplazarme hacia la respuesta que debería estar en la parte superior. Wow ... –

1

Una posible solución no sería para analizar el resultado de:

$ git reflog show myBranch 

y ver si su hash es en ella.

C:\Prog\Git\tests\rep\main>git reflog show patches 
786a190 [email protected]{0}: rebase finished: refs/heads/patches onto 74630b983db476c323b1d3f6771e57484551240e 
8448d0f [email protected]{1}: master~1: updating HEAD 
74630b9 [email protected]{2}: commit: test2 
1e73e36 [email protected]{3}: branch: Created from master 

guardo esto como una respuesta Wiki de la Comunidad de recordar Igor Zevaka y comentarios Chris Johnsen 's:

Ojalá que el trabajo después de un clon?
Bastante seguro que su reflog se inicia después de que usted clone un control remoto. Entonces, si una rama tenía una confirmación antes del clon, no aparecería en el reflog.

También hay problemas con los empujes, las rebases, las recuperaciones (para las ramas de 'seguimiento remoto') y las extracciones (ya sea fusionar o rebasear) donde solo la nueva sugerencia de sugerencia termina el reflog.
También los reflogs están deshabilitados por defecto en los repositorios desnudos (el destino más común para los empujes).
Además, si la "trampa" es un problema, solo es cuestión de editar un archivo de texto para agregar o eliminar entradas de reflog, pero es una prueba más grande alterar el gráfico del historial en sí.

+0

¿Funcionaría eso después de un clon? Bastante seguro de que tu reflog comienza después de que clones un control remoto. Entonces, si una rama tenía una confirmación antes del clon, no aparecería en el reflog. –

+0

Derecha, @Igor Zevaka. También hay problemas con los empujes y las rebases (donde solo el nuevo commit commit termina el reflog). Además, los reflogs están deshabilitados por defecto en los repositorios desnudos (el destino más común para los empujes). Además, si “trampa” es un problema, es sólo una cuestión de editar un archivo de texto para agregar o eliminar entradas reflog, pero es una prueba más grande para alterar el gráfico de la historia en sí. Retire –

114

Puede pedir directamente git branch que se ramifica contienen el envío de datos en cuestión:

% git branch -a --contains 4f08c85ad 
* master 
    remotes/origin/bug_872 
    remotes/origin/bug_898 
    remotes/origin/master 
+5

opción '-a' a la lista de su rama local solamente – ismailsunni

+0

Una rama específica podría ser utilizado en lugar de' -a' por ejemplo, '$ git branch develop --contains 4f08c85ad' –

Cuestiones relacionadas