tipos - Encontrar de qué rama proviene un git commit
git ver archivos modificados (12)
¿Hay alguna manera de averiguar de qué rama proviene un commit dado su sha1?
Puntos de bonificación si puedes decirme cómo lograr esto usando Ruby Grit.
TL; DR:
Use lo siguiente si le interesan los estados de salida de shell:
-
branch-current
- el nombre de la rama actual -
branch-names
- limpiar nombres de rama (uno por línea) -
branch-name
: asegúrese de que solo se devuelva unabranch-names
debranch-names
Tanto branch-name
branch-names
aceptan una confirmación como argumento, y se establecen de forma predeterminada en HEAD
si no se proporciona.
Alias útiles en scripting
branch-current = "symbolic-ref --short HEAD" # https://.com/a/19585361/5353461
branch-names = !"[ -z /"$1/" ] && git branch-current 2>/dev/null || git branch --format=''%(refname:short)'' --contains /"${1:-HEAD}/" #" # https://.com/a/19585361/5353461
branch-name = !"br=$(git branch-names /"$1/") && case /"$br/" in *$''//n''*) printf /"Multiple branches://n%s/" /"$br/">&2; exit 1;; esac; echo /"$br/" #"
Compromiso solo accesible desde una sola rama
% git branch-name eae13ea
master
% echo $?
0
- La salida es para RETIRAR
- El valor de salida es
0
.
Compromiso accesible desde múltiples sucursales.
% git branch-name 4bc6188
Multiple branches:
attempt-extract
master%
% echo $?
1
- La salida es a STDERR
- El valor de salida es
1
.
Debido al estado de salida, estos pueden ser construidos de forma segura. Por ejemplo, para obtener el control remoto utilizado para buscar:
remote-fetch = !"branch=$(git branch-name /"$1/") && git config branch./"$branch/".remote || echo origin #"
Actualización diciembre 2013:
sschuberth comments
git-what-branch
(el script de Perl, ver más abajo) parece que ya no se mantiene.
git-when-merged
es una alternativa escrita en Python que funciona muy bien para mí.
Se basa en " Buscar confirmación de fusión que incluye una confirmación específica ".
git when-merged [OPTIONS] COMMIT [BRANCH...]
Averigüe cuándo se ha fusionado una confirmación en una o más ramas.
Encuentre la confirmación de fusión que llevó aCOMMIT
a la (s) sucursal (es) especificada (s).Específicamente, busque el compromiso más antiguo en el historial del primer padre de
BRANCH
que contiene elCOMMIT
como un antepasado.
Respuesta original de septiembre de 2010:
Sebastien Douche acaba de twitted (16 minutos antes de esta respuesta):
git-what-branch : descubre en qué rama está un commit, o cómo llegó a una rama con nombre
Este es un git-what-branch de Seth Robertson que parece muy interesante:
SINOPSIS
git-what-branch [--allref] [--all] [--topo-order | --date-order ]
[--quiet] [--reference-branch=branchname] [--reference=reference]
<commit-hash/tag>...
VISIÓN GENERAL
Díganos (de forma predeterminada) la ruta causal más temprana de confirmaciones y fusiones para hacer que la confirmación solicitada llegue a una rama nombrada.
Si se realizó una confirmación directamente en una rama nombrada, obviamente esa es la ruta más antigua.Por primera ruta causal, nos referimos a la ruta que se fusionó en una rama con nombre la primera, por tiempo de confirmación (a menos que se especifique
--topo-order
).ACTUACIÓN
Si muchas ramas (p. Ej., Cientos) contienen la confirmación, el sistema puede tardar mucho tiempo (para una confirmación en particular en el árbol de Linux, tomó 8 segundos explorar una rama, pero había más de 200 ramas candidatas) para rastrear el camino a cada cometer
La selección de una--reference-branch --reference tag
particular--reference-branch --reference tag
para examinar será cientos de veces más rápida (si tiene cientos de ramas candidatas).EJEMPLOS
# git-what-branch --all 1f9c381fa3e0b9b9042e310c69df87eaf9b46ea4
1f9c381fa3e0b9b9042e310c69df87eaf9b46ea4 first merged onto master using the following minimal temporal path:
v2.6.12-rc3-450-g1f9c381 merged up at v2.6.12-rc3-590-gbfd4bda (Thu May 5 08:59:37 2005)
v2.6.12-rc3-590-gbfd4bda merged up at v2.6.12-rc3-461-g84e48b6 (Tue May 3 18:27:24 2005)
v2.6.12-rc3-461-g84e48b6 is on master
v2.6.12-rc3-461-g84e48b6 is on v2.6.12-n
[...]
Este programa no tiene en cuenta los efectos de elegir el compromiso de interés, solo operaciones de fusión.
Aparte de buscar en todo el árbol hasta que encuentre un hash coincidente, no.
Como experimento, hice un enlace posterior a la confirmación que almacena información sobre la rama actualmente activada en los metadatos de confirmación. También modifiqué ligeramente gitk para mostrar esa información.
Puede verlo aquí: https://github.com/pajp/branch-info-commits
Este simple comando funciona como un amuleto:
git name-rev <SHA>
Por ejemplo (donde prueba-rama es el nombre de la rama):
git name-rev 651ad3a
251ad3a remotes/origin/test-branch
Incluso esto funciona para escenarios complejos como: origin/branchA/ /branchB /commit<SHA1> /commit<SHA2>
Aquí git name-rev commit<SHA2>
devuelve branchB
La opción del hombre pobre es usar la herramienta tig
1 en HEAD
, buscar el compromiso y luego seguir visualmente la línea desde ese compromiso hasta que se vea un compromiso de fusión. El mensaje de combinación predeterminado debe especificar qué rama se fusiona con dónde :)
1 Tig es una interfaz de modo de texto basada en ncurses para git. Funciona principalmente como un navegador de repositorio Git, pero también puede ayudar en la preparación de cambios para la confirmación a nivel de trozos y actuar como un paginador para la salida de varios comandos Git.
Para encontrar la sucursal local
grep -lR YOUR_COMMIT .git/refs/heads | sed ''s/.git//refs//heads////g''
Para encontrar una sucursal remota
grep -lR $commit .git/refs/remotes | sed ''s/.git//refs//remotes////g''
Por ejemplo, para encontrar que c0118fa
commit proviene de redesign_interactions
* ccfd449 (HEAD -> develop) Require to return undef if no digits found
* 93dd5ff Merge pull request #4 from KES777/clean_api
|/
| * 39d82d1 Fix tc0118faests for debugging debugger internals
| * ed67179 Move &push_frame out of core
| * 2fd84b5 Do not lose info about call point
| * 3ab09a2 Improve debugger output: Show info about emitted events
| * a435005 Merge branch ''redesign_interactions'' into clean_api
| |/
| | * a06cc29 Code comments
| | * d5d6266 Remove copy/paste code
| | * c0118fa Allow command to choose how continue interaction
| | * 19cb534 Emit &interact event
Deberías correr:
git log c0118fa..HEAD --ancestry-path --merges
Y desplácese hacia abajo para encontrar el último comando de fusión . Cual es:
commit a435005445a6752dfe788b8d994e155b3cd9778f
Merge: 0953cac a06cc29
Author: Eugen Konkov
Date: Sat Oct 1 00:54:18 2016 +0300
Merge branch ''redesign_interactions'' into clean_api
UPD
O simplemente un comando:
git log c0118fa..HEAD --ancestry-path --merges --oneline --color | tail -n 1
Si bien Dav tiene razón al afirmar que la información no se almacena directamente, eso no significa que nunca pueda averiguarlo. Aquí hay algunas cosas que puedes hacer.
Encuentra las ramas en las que está comprometido
git branch --contains <commit>
Esto le dirá todas las ramas que tienen el compromiso dado en su historia. Obviamente, esto es menos útil si el compromiso ya se ha fusionado.
Busca los reflogs
Si está trabajando en el repositorio en el que se realizó la confirmación, puede buscar en los reflogs la línea para esa confirmación. Los reflogs con más de 90 días se eliminan mediante git-gc, por lo que si el compromiso es demasiado antiguo, no lo encontrará. Dicho esto, puedes hacer esto:
git reflog show --all | grep a871742
para encontrar commit a871742. La salida debería ser algo como esto:
a871742 refs/heads/completion@{0}: commit (amend): mpc-completion: total rewrite
lo que indica que el compromiso se realizó en la rama "finalización". La salida predeterminada muestra hashes de confirmación abreviados, así que asegúrese de no buscar el hash completo o no encontrará nada.
git reflog show
es en realidad solo un alias para git log -g --abbrev-commit --pretty=oneline
, así que si quieres jugar con el formato de salida para hacer diferentes cosas disponibles para grep, ¡ese es tu punto de partida!
Si no está trabajando en el repositorio donde se realizó la confirmación, lo mejor que puede hacer en este caso es examinar los registros y encontrar cuándo se introdujo por primera vez la confirmación en su repositorio; Con un poco de suerte, conseguiste la rama con la que estaba comprometido. Esto es un poco más complejo, porque no se puede caminar simultáneamente el árbol de confirmación y los reflogs. Usted querría analizar la salida de reflog, examinando cada hash para ver si contiene la confirmación deseada o no.
Encuentra un subsiguiente merge commit
Esto depende del flujo de trabajo, pero con buenos flujos de trabajo, las confirmaciones se realizan en las ramas de desarrollo que luego se fusionan. Usted podría hacer esto:
git log --merges <commit>..
para ver las combinaciones de combinaciones que tienen la confirmación dada como un antepasado. (Si la confirmación solo se fusionó una vez, la primera debería ser la combinación que está buscando; de lo contrario, tendrá que examinar algunas, supongo). El mensaje de confirmación de combinación debe contener el nombre de la rama que se fusionó.
Si desea poder contar con hacer esto, puede usar la --no-ff
para git merge
para forzar la creación de un compromiso de fusión incluso en el caso de avance rápido. (Sin embargo, no se ponga demasiado ansioso, eso podría volverse confuso si se usa en exceso). La respuesta de VonC a una pregunta relacionada explica con mucho detalle este tema.
Si el OP está tratando de determinar el historial que fue atravesado por una rama cuando se creó una confirmación en particular ("averiguar de qué rama proviene una confirmación dada su sha1"), entonces no hay registros en la base de datos de objetos git que muestra qué rama llamada estaba vinculada a lo que el historial de cometer.
(Publiqué esto como respuesta en respuesta a un comentario)
Esperemos que este guión ilustre mi punto:
rm -rf /tmp/r1 /tmp/r2; mkdir /tmp/r1; cd /tmp/r1
git init; git config user.name n; git config user.email [email protected]
git commit -m"empty" --allow-empty; git branch -m b1; git branch b2
git checkout b1; touch f1; git add f1; git commit -m"Add f1"
git checkout b2; touch f2; git add f2; git commit -m"Add f2"
git merge -m"merge branches" b1; git checkout b1; git merge b2
git clone /tmp/r1 /tmp/r2; cd /tmp/r2; git fetch origin b2:b2
set -x;
cd /tmp/r1; git log --oneline --graph --decorate; git reflog b1; git reflog b2;
cd /tmp/r2; git log --oneline --graph --decorate; git reflog b1; git reflog b2;
La salida muestra la falta de alguna forma de saber si la confirmación con ''Agregar f1'' provino de la rama b1 o b2 del clon remoto / tmp / r2
(últimas líneas de la salida aquí)
+ cd /tmp/r1
+ git log --oneline --graph --decorate
* f0c707d (HEAD, b2, b1) merge branches
|/
| * 086c9ce Add f1
* | 80c10e5 Add f2
|/
* 18feb84 empty
+ git reflog b1
f0c707d b1@{0}: merge b2: Fast-forward
086c9ce b1@{1}: commit: Add f1
18feb84 b1@{2}: Branch: renamed refs/heads/master to refs/heads/b1
18feb84 b1@{3}: commit (initial): empty
+ git reflog b2
f0c707d b2@{0}: merge b1: Merge made by the ''recursive'' strategy.
80c10e5 b2@{1}: commit: Add f2
18feb84 b2@{2}: branch: Created from b1
+ cd /tmp/r2
+ git log --oneline --graph --decorate
* f0c707d (HEAD, origin/b2, origin/b1, origin/HEAD, b2, b1) merge branches
|/
| * 086c9ce Add f1
* | 80c10e5 Add f2
|/
* 18feb84 empty
+ git reflog b1
f0c707d b1@{0}: clone: from /tmp/r1
+ git reflog b2
f0c707d b2@{0}: fetch origin b2:b2: storing head
Trato con el mismo problema (jenkins multibranch pipeline): tener solo confirmar información y tratar de encontrar un nombre de sucursal de donde provino originalmente este compromiso. Debe funcionar para sucursales remotas, no hay copias locales disponibles.
Esto es con lo que trabajo:
git rev-parse HEAD | xargs git name-rev
Opcionalmente puedes despojar la salida:
git rev-parse HEAD | xargs git name-rev | cut -d'' '' -f2 | sed ''s/remotes//origin////g''
git branch --contains <ref>
es el comando de "porcelana" más obvio para hacer esto. Si desea hacer algo similar con solo comandos de "fontanería":
COMMIT=$(git rev-parse <ref>) # expands hash if needed
for BRANCH in $(git for-each-ref --format "%(refname)" refs/heads); do
if $(git rev-list $BRANCH | fgrep -q $COMMIT); then
echo $BRANCH
fi
done
(crosspost de esta respuesta SO )