2010-04-25 16 views

Respuesta

633

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.

Encuentra ramas de la confirmación es el

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.

Buscar los reflogs

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.

Encuentra una fusión posterior cometer

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.

+4

+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

+8

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

+0

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

-3

Además de buscar en todo el árbol hasta que encuentre un hash coincidente, no.

+2

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

41

actualización diciembre 2013:

sschuberthcomments

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 cometer COMMIT 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 el COMMIT 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.

+2

'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

+0

@sschuberth gracias por esta actualización. He incluido su comentario en la respuesta para una mayor visibilidad. – VonC

3

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

+1

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

+0

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

4
opción

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.

5

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)

16

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 
+2

Esta fue la única solución que me dio el resultado deseado. Intenté el resto. – crafter

+0

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

+0

@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 –

-1

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' 
+0

algunas explicaciones de sus ejemplos serán geniales –

0

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 
+0

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? –

+0

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

2

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

+0

Usted me salvó el día. Esta es la solución perfecta. –

+0

Y tomó solo 8 años para esta solución perfecta. ¡Gracias! – S1J0

Cuestiones relacionadas