¿Hay alguna forma de averiguar de qué rama proviene una confirmación dada su sha1?Encontrar qué rama ha cometido un commit de git desde
Puntos de bonificación si me puede decir cómo lograr esto con Ruby Grit.
¿Hay alguna forma de averiguar de qué rama proviene una confirmación dada su sha1?Encontrar qué rama ha cometido un commit de git desde
Puntos de bonificación si me puede decir cómo lograr esto con Ruby Grit.
Si bien Dav tiene razón en que la información no está almacenada directamente, eso no significa que usted nunca pueda enterarse. Aquí hay algunas cosas que puede hacer.
git branch --contains <commit>
Esto le dirá todas las ramas que han dado la cometen en su historia. Obviamente, esto es menos útil si la confirmación ya se ha fusionado.
Si está trabajando en el repositorio en el que la confirmación fue hecha, puede buscar los reflogs de la línea para que se comprometan. Refrescos anteriores a 90 días son eliminados por git-gc, por lo que si la confirmación es demasiado antigua, no la encontrará. Dicho esto, puede hacer esto:
git reflog show --all | grep a871742
para encontrar commit a871742. La salida debe ser algo como esto:
a871742 refs/heads/[email protected]{0}: commit (amend): mpc-completion: total rewrite
lo que indica que la confirmación fue hecha en la rama "finalización". La salida predeterminada muestra valores hash 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
, por lo 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 reflogs y encontrar cuándo se introdujo por primera vez la confirmación en su repositorio; con un poco de suerte, trajiste la sucursal con la que estaba comprometida. Esto es un poco más complejo, porque no puede caminar tanto en el árbol de confirmación como en los reflogs simultáneamente. Desea analizar el resultado de la entrada de nuevo, examinando cada hash para ver si contiene la confirmación deseada o no.
Este es el flujo de trabajo dependiente, pero con buenos flujos de trabajo, cometa, está hecha de ramas de desarrollo que luego se fusionaron en Usted puede hacer esto:.
git log --merges <commit>..
para ver merge commits que tienen el commit dado como ancestro. (Si la confirmación solo se fusionó una vez, la primera debería ser la fusión que está buscando, de lo contrario, tendrá que examinar algunas, supongo). El mensaje de confirmación de fusión debería contener el nombre de la rama que se fusionó.
Si desea poder contar con esto, puede utilizar la opción --no-ff
en git merge
para forzar la creación de la asignación de fusión incluso en el caso de avance rápido. (No se anime demasiado, sin embargo, eso podría ofuscarse si se usa en exceso). El answer to a related question de VonC brinda mucha ayuda sobre este tema.
Además de buscar en todo el árbol hasta que encuentre un hash coincidente, no.
No quiero desestimar esto, porque en rigor, es cierto que git no almacena permanentemente esa información, pero a menudo es posible descubrirla. Ver mi respuesta – Cascabel
actualización diciembre 2013:
git-what-branch
(Perl guión, ver más abajo) no parece ser mantenido más.
git-when-merged
es una alternativa escrito en Python que está trabajando muy bien para mí.
Se basa en "Find merge commit which include a specific commit".
git when-merged [OPTIONS] COMMIT [BRANCH...]
Búsqueda Cuando una confirmación se fusionó con una o más ramas.
Encuentra la fusión cometerCOMMIT
que provocó en la rama especificada (s).Específicamente, busque la confirmación más antigua en la historia del primer padre de
BRANCH
que contiene elCOMMIT
como antecesor.
Respuesta original septiembre de 2010:
Sebastien Douche simplemente twitted (16 minutos antes de la presente OS respuesta):
git-what-branch: Descubre qué rama una confirmación está en, o cómo llegó a una rama llamada
Esta es una Perl script 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>...
RESUMEN
decirnos (por defecto) el camino causal más temprano de compromisos y fusiones para causar la la confirmación solicitada llegó a una rama nombrada.
Si se realizó una confirmación directamente en una rama con nombre, esa es obviamente la ruta más temprana.Por la ruta causal más temprana, nos referimos a la ruta que se fusionó en una rama con nombre la más temprana, por tiempo de confirmación (a menos que se especifique
--topo-order
).RENDIMIENTO
Si muchas ramas (por ejemplo, cientos) contienen la confirmación, el sistema puede tardar mucho tiempo (para una confirmación en concreto en el árbol de Linux, se tardó 8 segundos para explorar una rama, pero hay fueron más de 200 ramas candidatas) para rastrear el camino a cada compromiso.
La selección de un 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 cereza recoger el envío de datos de interés, solamente fusionar sus operaciones.
'git-what-branch' ya no parece mantenerse. [git-when-merged] (https://github.com/mhagger/git-when-merged) es una alternativa escrita en Python que funciona muy bien para mí. – sschuberth
@sschuberth gracias por esta actualización. He incluido su comentario en la respuesta para una mayor visibilidad. – VonC
Como un experimento, hice un gancho post-commit que almacena información sobre la rama actualmente desprotegida en los metadatos de confirmación. También modifiqué ligeramente gitk para mostrar esa información.
Puede verificarlo aquí: https://github.com/pajp/branch-info-commits
Pero si quieres agregar metadatos, ¿por qué no usar las notas de git, en lugar de jugar con los encabezados de las confirmaciones? Consulte http://stackoverflow.com/questions/5212957/how-to-change-git-commit-message-without-changing-commit-hash/5213110#5213110, http://stackoverflow.com/questions/7298749/is -hay-un-camino-para-bien-cambiar-un-git-ramas-historia-cuando-bifurcaciones-de-exis/7299044 # 7299044 o http://stackoverflow.com/questions/7101158/is-git -notes-the-intended-way-to-add-category-style-information-to-a-commit/7102923 # 7102923 – VonC
Para ser sincero, no sabía que existían notas falsas cuando escribí eso. Sí, usar notas de git para lograr lo mismo probablemente sea una mejor idea. – pajp
del hombre pobre es utilizar the tool tig
en HEAD
, buscar la confirmación, y luego seguir visualmente la línea de esa confirmación de vuelta hasta una fusión cometer es visto. El mensaje de combinación por defecto debería especificar qué rama se fusionaron para conseguir donde :)
Tig es una interfaz en modo texto basado en ncurses para Git. Funciona principalmente como un navegador de repositorio de Git, pero también puede ayudar a organizar los cambios para la confirmación a nivel de fragmento y actuar como un busca para la salida de varios comandos de Git.
git branch --contains <ref>
es el comando de "porcelana" más obvio para hacer esto. Si quiere hacer algo similar con solamente "cañerías" comandos:
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 this SO answer)
Por ejemplo, para encontrar que c0118fa
commit vinieron 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ía ejecutar :
git log c0118fa..HEAD --ancestry-path --merges
Y sc rodar hacia abajo para encontrar la última fusionar commit.Que 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 solo comando:
git log 56a44a5..HEAD --ancestry-path --merges --oneline --color | tail -n 1
Esta fue la única solución que me dio el resultado deseado. Intenté el resto. – crafter
Tenga en cuenta que esto solo funciona si los resúmenes de confirmación de fusión contienen los nombres de rama utilizados en las fusiones, que de forma predeterminada suelen hacer. Sin embargo, 'git merge -m" Cualquier cadena aquí "' oscurecerá la fuente y la información de la rama de destino. – qneill
@qneill: No, la fusión siempre tiene información sobre las ramas fusionadas: 'Merge: f6b70fa d58bdcb'. Puedes nombrar tu commit de fusión como tú. No tendré la materia –
Para encontrar rama local
grep -lR YOUR_COMMIT .git/refs/heads | sed 's/.git\/refs\/heads\///g'
Para encontrar la rama remota
grep -lR $commit .git/refs/remotes | sed 's/.git\/refs\/remotes\///g'
algunas explicaciones de sus ejemplos serán geniales –
Si el OP intenta determinar el historial que fue recorrido por una bifurcación cuando se creó una confirmación en particular ("averigüe de qué rama proviene una confirmación dada su sha1"), entonces sin el reflog hay sin registros en la base de datos de objetos git que muestra qué rama con nombre estaba vinculada a qué historial de commit.
(he publicado esto como una respuesta en respuesta a un comentario)
Con suerte este script ilustra 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 manera de saber si la cometen con ' Añadir f1' vino de b1 b2 sucursal o desde el control remoto clon/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 [email protected]{0}: merge b2: Fast-forward
086c9ce [email protected]{1}: commit: Add f1
18feb84 [email protected]{2}: Branch: renamed refs/heads/master to refs/heads/b1
18feb84 [email protected]{3}: commit (initial): empty
+ git reflog b2
f0c707d [email protected]{0}: merge b1: Merge made by the 'recursive' strategy.
80c10e5 [email protected]{1}: commit: Add f2
18feb84 [email protected]{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 [email protected]{0}: clone: from /tmp/r1
+ git reflog b2
f0c707d [email protected]{0}: fetch origin b2:b2: storing head
Y cuál es el resultado para 'git log 80c10e5..HEAD --ancestry-path --merges --oneline --color | tail -n 1' y 'git log 086c9ce..HEAD --ancestry-path --merges --oneline --color | tail -n 1' comandos para ambos casos? –
Los SHA por supuesto cambian cada vez que se ejecutan los comandos, para respetar los comandos que usé ** HEAD^1 ** y ** HEAD^2 ** en una nueva ejecución. Los comandos y salida son: '$ git log HEAD^1..HEAD --ancestry-path --merges --oneline --color | tail -n 1' que produce '376142d fusionar ramas' y' $ git log HEAD^2..HEAD --ancestry-path --merges --oneline --color | tail -n 1' que produce '376142d merge branches' - que muestra el resumen de commit de fusión, que (como afirmaba) se puede sobrescribir cuando se crea la fusión, posiblemente ofuscando el historial de la rama de la fusión. – qneill
Este simple comando funciona como un encanto:
git name-rev <SHA>
Por ejemplo (donde prueba de rama es el nombre de la sucursal):
git name-rev 651ad3a
251ad3a remotes/origin/test-branch
Incluso esto está trabajando para escenarios complejos como: origin/branchA/ /branchB /commit<SHA1> /commit<SHA2>
Aquí git name-rev commit<SHA2>
devuelve branchB
Usted me salvó el día. Esta es la solución perfecta. –
Y tomó solo 8 años para esta solución perfecta. ¡Gracias! – S1J0
+1. La absoluta ausencia de información para ese problema en particular te hace preguntar si realmente es un problema. Las sucursales pueden cambiar, cambiar de nombre o eliminarse en cualquier momento. Puede ser 'git describe' es suficiente, ya que las etiquetas (anotadas) se pueden ver como más significativas que las ramas. – VonC
Definitivamente estoy de acuerdo: las sucursales deben ser livianas y flexibles. Si adoptas un flujo de trabajo en el que esa información se vuelve importante, puedes usar la opción '--no-ff' para asegurarte de que siempre hay una confirmación de fusión, por lo que siempre puedes rastrear la ruta de una confirmación dada cuando se combina con el maestro . – Cascabel
ver [mi respuesta] (http://stackoverflow.com/questions/2706797/git-finding-what-branch-a-commit-came-from/3772472#3772472) haciendo referencia al script Perl de Seth, para una implementación interesante de ese algoritmo de búsqueda. – VonC