Los diferentes métodos a continuación son formas pragmáticas, útiles, de trabajo para inferir una respuesta probable , pero tengamos en cuenta que en git la pregunta en sí es un malentendido, los commits no provienen de las ramas. Las ramas van y vienen, se mueven, solo los commits representan la verdadera historia del repositorio. Por otra parte, esta no es una manera de decir que las siguientes soluciones son malas. Solo sé que ninguno de ellos da una respuesta totalmente confiable, que no se puede obtener por diseño en git. (Un caso simple es ramas eliminadas: me bifurco, me comprometo dos veces, me uno a otra rama, borro la primera rama. ¿De dónde "viene" el commit?
RomainValeri
1
Tengo un caso en el que extraigo explícitamente un clon superficial de profundidad 1 de una etiqueta. Es barato, fácil y eficiente ... y hasta ahora hacía todo lo que quería maravillosamente. Ahora que me gustaría saber en qué rama estaba la etiqueta, me manché, al menos por ese detalle. No siempre puedes ir a casa, jajaja
Paul Hodges
Respuestas:
865
Si bien Dav tiene razón en que la información no se almacena directamente, eso no significa que nunca pueda averiguarlo. Aquí hay algunas cosas que puedes hacer.
Encuentra sucursales en las que se compromete
git branch -a --contains <commit>
Esto le dirá todas las ramas que tienen el compromiso dado en su historia. Obviamente, esto es menos útil si la confirmación ya se ha fusionado.
Buscar los registros
Si está trabajando en el repositorio en el que se realizó la confirmación, puede buscar en los reflogs la línea de esa confirmación. Los registros de más de 90 días son eliminados por git-gc, por lo que si la confirmación es demasiado antigua, no la encontrará. Dicho esto, puedes hacer esto:
git reflog show --all | grep a871742
para encontrar cometer a871742. Tenga en cuenta que DEBE utilizar los primeros 7 dígitos abreviados de la confirmación. La salida debería ser algo como esto:
a871742 refs/heads/completion@{0}: commit (amend): mpc-completion: total rewrite
indicando que la confirmación se realizó en la rama "finalización". El resultado predeterminado muestra hashes de confirmación abreviados, así que asegúrese de no buscar el hash completo o no encontrará nada.
git reflog show en realidad es 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 reflogs y encontrar cuándo la confirmación se introdujo por primera vez en su repositorio; con suerte, buscaste la rama a la que estaba comprometido. Esto es un poco más complejo, porque no puedes recorrer el árbol de confirmaciones y los registros a la vez. Desea analizar el resultado de reflog, examinando cada hash para ver si contiene el commit deseado o no.
Encuentre una confirmación de fusión posterior
Esto depende del flujo de trabajo, pero con buenos flujos de trabajo, se realizan confirmaciones en las ramas de desarrollo que luego se fusionan. Puede hacer esto:
git log --merges <commit>..
para ver los commits de fusión que tienen el commit dado como 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 esto, puede usar la --no-ffopción git mergepara forzar la creación de confirmación 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 elabora útilmente este tema.
+1. La pura ausencia de información para ese tema en particular te hace preguntarte si realmente es un problema. Las sucursales pueden cambiar, cambiar de nombre o eliminarse en cualquier momento. Puede ser git describesuficiente, ya que las etiquetas (anotadas) se pueden ver como más significativas que las ramas.
VonC
99
Definitivamente estoy de acuerdo: las ramas deben ser ligeras y flexibles. Si adopta un flujo de trabajo en el que esa información se vuelve importante, puede usar la --no-ffopción para asegurarse de que siempre haya una confirmación de fusión, de modo que siempre pueda rastrear la ruta de una confirmación dada a medida que se fusiona con el maestro.
Cascabel
32
Para su información, si desea encontrar confirmaciones que solo existen en el control remoto, agregue la -abandera al primer comando, por ejemplogit branch -a --contains <commit>
Jonathan Day,
8
@ JonathanDay: No, eso encontrará confirmaciones en cualquier rama. Si solo quieres unos en el control remoto, úsalo -r.
Cascabel
77
@SimonTewsi Como dije, si realmente es un problema, úselo merge --no-ffpara registrar de manera confiable el nombre de la sucursal cuando se fusione. Pero, de lo contrario, piense en los nombres de las ramas como etiquetas cortas temporales y confirme las descripciones como permanentes. "¿Con qué nombre corto nos referimos a esto durante el desarrollo?" realmente no debería ser una pregunta tan importante como "¿qué hace este compromiso?"
Cascabel
155
Este simple comando funciona como un encanto:
git name-rev <SHA>
Por ejemplo (donde test-branch es el nombre de la rama):
Y solo tomó 8 años para esta solución perfecta. ¡Gracias!
S1J0
66
Me pareció git name-rev --name-only <SHA>más útil para obtener solo el nombre de la sucursal. Mi pregunta ... ¿Puede devolver más de una rama en cualquier circunstancia?
git-what-branch(El script de Perl, ver más abajo) ya no parece mantenerse.
git-when-mergedes una alternativa escrita en Python que me funciona muy bien.
Encuentre cuándo una confirmación se fusionó en una o más ramas.
Encuentre la confirmación de fusión que se introdujo COMMITen las RAMAS especificadas.
Específicamente, busque el commit más antiguo en el historial del primer padre BRANCHque contiene el COMMITcomo ancestro.
Indíquenos (de manera predeterminada) la ruta causal más temprana de los commits y las fusiones para hacer que el commit solicitado llegue a una rama con nombre. Si se realizó una confirmación directamente en una rama con nombre, obviamente esa es la ruta más temprana.
Por ruta causal más temprana, nos referimos a la ruta que se fusionó en una rama con nombre la primera, por tiempo de confirmación (a menos que --topo-orderse especifique).
ACTUACIÓN
Si muchas ramas (por ejemplo, cientos) contienen la confirmación, el sistema puede tardar mucho tiempo (para una confirmación particular en el árbol de Linux, tardó 8 segundos en explorar una rama, pero había más de 200 ramas candidatas) para rastrear el camino a cada compromiso
La selección de un particular --reference-branch --reference tagpara 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 fusiona las operaciones.
git-what-branchParece que ya no se mantiene. git-when-merged es una alternativa escrita en Python que funciona muy bien para mí.
sschuberth
@sschuberth gracias por esta actualización. He incluido tu comentario en la respuesta para mayor visibilidad.
VonC
37
Por ejemplo, para encontrar que c0118facommit vino 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 la última confirmación 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
Esta fue la única solución que me dio el resultado deseado. Probé el resto.
crafter
Tenga en cuenta que esto solo funciona si los resúmenes de confirmación de fusión contienen los nombres de las ramas utilizados en las fusiones, que por defecto suelen contener. Sin embargo git merge -m"Any String Here", oscurecerá la información de la sucursal de origen y destino.
qneill
@qneill: No, la fusión siempre tiene información sobre ramas fusionadas: Merge: f6b70fa d58bdcb. Puede nombrar su compromiso de fusión como lo desee. No tendré materia
Eugen Konkov
1
@EugenKonkov una vez que las ramas han atravesado la fusión, el historial sobre el camino en el gráfico del que provienen se deja en el registro, pero no en la base de datos de objetos git.
Publiqué
UPD versión funciona para mí, simple comando que encuentra el original se comprometen
vpalmu
9
git branch --contains <ref>es el comando de "porcelana" más obvio para hacer esto. Si desea hacer algo similar con solo comandos de "plomerí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
Actualicé la descripción. Gracias por los comentarios.
phyatt
4
La opción de un hombre pobre es utilizar la herramienta tig1 sobre HEAD, buscar la confirmación, y luego seguir visualmente la línea desde que cometen una copia de seguridad hasta que una combinación de confirmación se ve. El mensaje de fusión predeterminado debe especificar en qué rama se fusiona y 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 a organizar los cambios para confirmar a nivel de fragmento y actuar como un localizador para la salida de varios comandos Git.
Como experimento, hice un enlace posterior a la confirmación 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.
Para ser honesto, no sabía que existían notas de git cuando escribí eso. Sí, usar notas git para lograr lo mismo es probablemente una mejor idea.
pajp
3
Trato con el mismo problema ( canalización de múltiples ramas de Jenkins ): tener solo información de confirmación e intentar encontrar un nombre de sucursal de donde proviene originalmente esta confirmación. Debe funcionar para sucursales remotas, las copias locales no están disponibles.
Esto es con lo que trabajo:
git rev-parse HEAD | xargs git name-rev
Opcionalmente, puede quitar la salida:
git rev-parse HEAD | xargs git name-rev | cut -d' ' -f2 | sed 's/remotes\/origin\///g'
Si el OP está tratando de determinar el historial que atravesó una rama cuando se creó una confirmación particular ("averigüe de qué rama proviene una confirmación dado su valor hash SHA-1"), entonces sin el registro no hay ningún registros en la base de datos de objetos Git que muestra qué rama nombrada estaba vinculada a qué historial de confirmación.
(Publiqué esto como respuesta en respuesta a un comentario).
¿Y cuál es la salida git log 80c10e5..HEAD --ancestry-path --merges --oneline --color | tail -n 1y los git log 086c9ce..HEAD --ancestry-path --merges --oneline --color | tail -n 1comandos para ambos casos?
Eugen Konkov
Los SHA, por supuesto, cambian cada vez que se ejecutan los comandos, para respetar sus comandos, utilicé HEAD ^ 1 y HEAD ^ 2 en una nueva ejecución. Los comandos y la salida son: $ git log HEAD^1..HEAD --ancestry-path --merges --oneline --color | tail -n 1que produce376142d merge branches y $ git log HEAD^2..HEAD --ancestry-path --merges --oneline --color | tail -n 1qué rendimiento 376142d merge branches : que muestra el resumen de confirmación de fusión, que (como estaba afirmando) se puede sobrescribir cuando se crea la fusión, posiblemente ofuscando el historial de ramificación de la fusión.
qneill
0
TL; DR:
Use lo siguiente si le interesan los estados de salida de shell:
branch-current - el nombre de la sucursal actual
branch-names - nombres de sucursal limpios (uno por línea)
branch-name - Asegúrese de que solo se devuelva una rama de branch-names
Ambos branch-namey branch-namesaceptan un commit como argumento, y por defecto HEADsi no se da ninguno.
Realmente no quiero desestimar esto, porque estrictamente hablando es cierto que git no almacena esa información permanentemente, pero de todos modos es muy posible averiguarlo. Mira mi respuesta.
Respuestas:
Si bien Dav tiene razón en que la información no se almacena directamente, eso no significa que nunca pueda averiguarlo. Aquí hay algunas cosas que puedes hacer.
Encuentra sucursales en las que se compromete
Esto le dirá todas las ramas que tienen el compromiso dado en su historia. Obviamente, esto es menos útil si la confirmación ya se ha fusionado.
Buscar los registros
Si está trabajando en el repositorio en el que se realizó la confirmación, puede buscar en los reflogs la línea de esa confirmación. Los registros de más de 90 días son eliminados por git-gc, por lo que si la confirmación es demasiado antigua, no la encontrará. Dicho esto, puedes hacer esto:
para encontrar cometer a871742. Tenga en cuenta que DEBE utilizar los primeros 7 dígitos abreviados de la confirmación. La salida debería ser algo como esto:
indicando que la confirmación se realizó en la rama "finalización". El resultado predeterminado muestra hashes de confirmación abreviados, así que asegúrese de no buscar el hash completo o no encontrará nada.
git reflog show
en realidad es solo un alias paragit 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 reflogs y encontrar cuándo la confirmación se introdujo por primera vez en su repositorio; con suerte, buscaste la rama a la que estaba comprometido. Esto es un poco más complejo, porque no puedes recorrer el árbol de confirmaciones y los registros a la vez. Desea analizar el resultado de reflog, examinando cada hash para ver si contiene el commit deseado o no.
Encuentre una confirmación de fusión posterior
Esto depende del flujo de trabajo, pero con buenos flujos de trabajo, se realizan confirmaciones en las ramas de desarrollo que luego se fusionan. Puede hacer esto:
para ver los commits de fusión que tienen el commit dado como 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 esto, puede usar la
--no-ff
opcióngit merge
para forzar la creación de confirmación 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 elabora útilmente este tema.fuente
git describe
suficiente, ya que las etiquetas (anotadas) se pueden ver como más significativas que las ramas.--no-ff
opción para asegurarse de que siempre haya una confirmación de fusión, de modo que siempre pueda rastrear la ruta de una confirmación dada a medida que se fusiona con el maestro.-a
bandera al primer comando, por ejemplogit branch -a --contains <commit>
-r
.merge --no-ff
para registrar de manera confiable el nombre de la sucursal cuando se fusione. Pero, de lo contrario, piense en los nombres de las ramas como etiquetas cortas temporales y confirme las descripciones como permanentes. "¿Con qué nombre corto nos referimos a esto durante el desarrollo?" realmente no debería ser una pregunta tan importante como "¿qué hace este compromiso?"Este simple comando funciona como un encanto:
git name-rev <SHA>
Por ejemplo (donde test-branch es el nombre de la rama):
Incluso esto funciona para escenarios complejos, como:
Aquí
git name-rev commit<SHA2>
vuelve branchB .fuente
git name-rev --name-only <SHA>
más útil para obtener solo el nombre de la sucursal. Mi pregunta ... ¿Puede devolver más de una rama en cualquier circunstancia?Actualización de diciembre de 2013:
comentarios sschuberth
Se basa en " Buscar confirmación de fusión que incluye una confirmación específica ".
Respuesta original de septiembre de 2010:
Sebastien Douche simplemente twitteó (16 minutos antes de esta respuesta SO):
Este es un script de Perl de Seth Robertson que parece muy interesante:
fuente
git-what-branch
Parece que ya no se mantiene. git-when-merged es una alternativa escrita en Python que funciona muy bien para mí.Por ejemplo, para encontrar que
c0118fa
commit vino deredesign_interactions
:Deberías correr:
Y desplácese hacia abajo para encontrar la última confirmación de fusión . Cual es:
Actualizar
O solo un comando:
fuente
git merge -m"Any String Here"
, oscurecerá la información de la sucursal de origen y destino.Merge: f6b70fa d58bdcb
. Puede nombrar su compromiso de fusión como lo desee. No tendré materiagit branch --contains <ref>
es el comando de "porcelana" más obvio para hacer esto. Si desea hacer algo similar con solo comandos de "plomería":(crosspost de esta respuesta SO )
fuente
khichar.anil cubrió la mayor parte de esto en su respuesta.
Solo estoy agregando la bandera que eliminará las etiquetas de la lista de nombres de revisión. Esto nos da:
fuente
La opción de un hombre pobre es utilizar la herramienta
tig
1 sobreHEAD
, buscar la confirmación, y luego seguir visualmente la línea desde que cometen una copia de seguridad hasta que una combinación de confirmación se ve. El mensaje de fusión predeterminado debe especificar en qué rama se fusiona y dónde :)fuente
Como experimento, hice un enlace posterior a la confirmación 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
fuente
Trato con el mismo problema ( canalización de múltiples ramas de Jenkins ): tener solo información de confirmación e intentar encontrar un nombre de sucursal de donde proviene originalmente esta confirmación. Debe funcionar para sucursales remotas, las copias locales no están disponibles.
Esto es con lo que trabajo:
Opcionalmente, puede quitar la salida:
fuente
Creo que alguien debería enfrentar el mismo problema que no puede encontrar la rama, aunque en realidad existe en una rama.
Será mejor que hagas todo primero:
Luego haga la búsqueda de sucursal:
o:
fuente
Si el OP está tratando de determinar el historial que atravesó una rama cuando se creó una confirmación particular ("averigüe de qué rama proviene una confirmación dado su valor hash SHA-1"), entonces sin el registro no hay ningún registros en la base de datos de objetos Git que muestra qué rama nombrada estaba vinculada a qué historial de confirmación.
(Publiqué esto como respuesta en respuesta a un comentario).
Esperemos que este script ilustre mi punto:
El resultado muestra la falta de alguna forma de saber si el commit con 'Add f1' vino de la rama b1 o b2 del clon remoto / tmp / r2.
(Últimas líneas de la salida aquí)
fuente
git log 80c10e5..HEAD --ancestry-path --merges --oneline --color | tail -n 1
y losgit log 086c9ce..HEAD --ancestry-path --merges --oneline --color | tail -n 1
comandos para ambos casos?$ git log HEAD^1..HEAD --ancestry-path --merges --oneline --color | tail -n 1
que produce376142d merge branches
y$ git log HEAD^2..HEAD --ancestry-path --merges --oneline --color | tail -n 1
qué rendimiento376142d merge branches
: que muestra el resumen de confirmación de fusión, que (como estaba afirmando) se puede sobrescribir cuando se crea la fusión, posiblemente ofuscando el historial de ramificación de la fusión.TL; DR:
Use lo siguiente si le interesan los estados de salida de shell:
branch-current
- el nombre de la sucursal actualbranch-names
- nombres de sucursal limpios (uno por línea)branch-name
- Asegúrese de que solo se devuelva una rama debranch-names
Ambos
branch-name
ybranch-names
aceptan un commit como argumento, y por defectoHEAD
si no se da ninguno.Alias útiles en scripting
Comprometerse solo accesible desde una sola rama
0
.Compromiso accesible desde múltiples ramas
1
.Debido al estado de salida, estos se pueden construir de forma segura. Por ejemplo, para obtener el control remoto utilizado para buscar:
fuente
Para encontrar la sucursal local:
Para encontrar la rama remota:
fuente
Además de buscar en todo el árbol hasta encontrar un hash que coincida, no.
fuente