Registro de Git: ¿Cómo identificar (incluso eliminar) la twig de tema que contiene confirmación?

En algunos casos, sería útil ver el nombre de la sucursal (incluso si se eliminó) que contiene las confirmaciones coincidentes cuando guardo el historial de Git.

Problema

Por ejemplo, la salida de git log --grep 'count to G' en el repository de Unite.vim es:

 commit 7b173ac0ebeadbb1eec17fd12faa1efdcaaa2bb1 Author: Kevin Ballard <kevin@sb.org> Date: Sun Jul 26 17:30:15 2015 -0700 Support passing a count to G The mapping for gg supported a count, but the mapping for G did not. Add support, and make it avoid networkingrawing candidates if a count is provided that is within the list of current candidates. 

El logging de la twig de esta confirmación es git log --oneline --graph 515b01c~..15db364 :

 * 15db364 Merge pull request #974 from kballard/better-gg-G-mappings |\ | * 0b39984 Map <C-Home> and <C-End> as well | * 79daa61 Teach gg to jump to the first candidate instead of the prompt | * 7b173ac Support passing a count to G |/ * 515b01c Fix #973 use buflisted() 

¿Cómo puedo mostrar la pull request #974 from kballard/better-gg-G-mappings (o branch 'name-of-the-branch' , etc.) en la descripción de commit de git log --grep 'count to G ?

Experiencias propias

Lo que encontré una posible solución para averiguar el nombre de la sucursal es search el SHA en git log --oneline --graph --all . Funciona con twigs existentes y eliminadas también, pero tengo que rastrear el gráfico hasta que la fusión se comprometa.

Otra solución sería git log --grep 'count to G' --source : muestra la reference a la que pertenece la confirmación después de la SHA, pero da información falsa cuando la twig fusionada se elimina (ya no existe).

Lo último que encontré útil es almacenar el nombre de la twig en la confirmación, pero ocupa mucho espacio si se escribe en el tema, y ​​se vuelve inútil si está en el cuerpo, porque --oneline no lo muestra). Puede ser ambiguo si se renombra la twig después de la confirmación, por lo que desapruebo esto como una posible solución.

Pregunta

¿Es posible mostrar el nombre de la twig (posible borrado) de cada confirmación en el git log ? ¿O cómo puedo averiguar eso?

Como señaló Jonathon Reinhart en un comentario , la información que desea simplemente no está disponible en git, y puede cambiar dinámicamente. Es posible (porque la información es estática) en algunos otros sistemas de control de versiones, como Mercurial. Pegaré otro bit (bastante largo, esta vez) del capítulo de teoría de grafos del libro en el que he estado (lentamente) trabajando. La nota de pie de página seis es particularmente relevante aquí. Nadie necesita leer nada de eso, por supuesto. 🙂

Dicho esto, git branch --all --contains <commit> es básicamente lo más cercano que se puede get sin search en los reflogs (si se retuvieron los reflogs para las twigs borradas, eso ayudaría con su pregunta original, pero (a) son no y (b) los reflogs solo duran por el time que los configures para que duren de todos modos: valor pnetworkingeterminado 30 días para las confirmaciones inalcanzables, 90 días para las alcanzables). En su caso particular, agregar y usar – --tags podría ser más apropiado. Tenga en count que las tags son permanentes y globales, como las twigs de Mercurial, por lo que en algunos aspectos las tags serían la forma de hacerlo (pero la respuesta de git es que no debería hacer esto, lo cual no es una gran respuesta, en realidad: )).

Resolviendo el problema relacionado que lo llevó a hacer la pregunta específica

Si abandonamos la pregunta que nos hiciste ("identifica la twig en la que se realizó la confirmación") y volvemos al enunciado original del problema, que voy a reformular aquí para "encontrar si una confirmación se fusionó mediante una request de extracción tal como está registrada en un post de logging "- ese Git puede resolverlo, aunque tendrá que escribir un poco de script. En este caso, lo que tenemos es:

  • un commit ID $commit
  • que puede (o no) estar "debajo" de una fusión de commit cuyo post de logging es "Merge pull request # [digits] from [string]", en la cadena comenzando desde el segundo padre de esa fusión commit, hasta el punto donde esta cadena de segundo padre se une al flujo de confirmaciones en la cadena de primer padre, probablemente directamente en el primer padre (pero sería bueno permitir que esté por debajo de ese punto, y de hecho es mucho más fácil hacerlo de esa manera).

Si $commit está, de hecho, en dicha cadena, quiere que el post de logging de la fusión se confirme.

Para get esto, necesitaremos ejecutar git rev-list para encontrar fusiones para inspeccionar, y luego volver a git rev-list para ver si se aplican las restricciones (el commit aparece en el lado del 2do padre de la combinación). Lo siguiente no está optimizado, ni siquiera probado, pero muestra la idea:

 git rev-list --merges --all | while read mhash; do msg=$(git log --no-walk --format=%s $mhash) case $msg in "Merge pull request #"*" from "*) ;; *) continue;; # apparently not a pull request esac if git rev-list ${mhash}^..${mhash}^2 | grep "^${commit}$" >/dev/null; then # we found it! echo "commit ${commit} is under merge ${mhash}: $msg" break fi done 

Esto probablemente debería reescribirse para que sea un poco más robusto (en caso de que el post de fusión de request de extracción no tenga ese formatting de cadena exacto, por ejemplo) y / o inteligente. También asume que las fusiones de requestes de extracción nunca se realizan como fusiones de pulpos (el command git rev-list específico que utiliza los dos selectores principales podría modificarse para evitar esa suposition, de nuevo se trata de mayor claridad).


El extracto del libro TL; DR – siéntase libre de saltear

Finalmente estamos listos para abordar una diferencia key entre Git y Mercurial. Recuerde la pregunta anterior del Capítulo 1 sobre cómo ubicar, identificar y relacionar commits, y mover commits de una twig a otra. En Mercurial, los commits se fijan permanentemente a una sola twig. Algunas de estas confirmaciones pueden tener en grado 0, es decir, pueden estar en los extremos frondosos de las twigs. Mercurial llama a estas cabezas . 4 Los localizamos por sus twigs; ellos definen los extremos de esas twigs. Dado que cada confirmación registra su identificador de confirmación padre (o dos ID en el caso de una combinación), podemos usar estos encabezados para llegar a cualquier otra confirmación en la twig (o de hecho, en todo el gráfico). Las routes DAG a los otros commits nos dan sus relaciones relativas.

4 En un DAG normal, veríamos el grado fuera en lugar del grado: los nodos con grado 0 son las hojas en nuestra definición formal prestada 1. Nuestros arcos DAG de compromiso se han invertido, por lo que cambiamos nuestro punto de vista. La palabra "hoja" proviene de la vista previa a la reversión, pero seguimos usándola aquí: Git llama a una confirmación con out-degree 0 una "confirmación raíz", por lo que llamar a los otros extremos "hojas" es lo suficientemente razonable. Git normalmente no se molesta con un término para ellos, pero por ahora, necesitamos una forma concisa para hablar sobre ellos.

[recorte]

Git usa un esquema radicalmente diferente. Los nodos de confirmación no retienen la información de la sucursal. Conservan sus identificadores de confirmación padre, al igual que Mercurial, pero encontrar todas las confirmaciones de hoja requiere la búsqueda de todo el repository. 5 Para acelerar esto, Git proporciona una forma general de reference externa en una estructura de datos separada del gráfico en sí. Estas references externas incluyen todas las twigs de Git (y las tags de Git, y muchas otras forms también).

Git llama a la confirmación a la que un nombre de sucursal señala una sugerencia de sugerencia . Los nombres de las twigs de Git no tienen que apuntar a los nodos hoja, y más de una reference externa puede apuntar a cualquier nodo dado (incluidos los nodos hoja). En efecto, cada reference externa agrega un arco entrante a su nodo. Esto proporciona accesibilidad a (algunos) nodos de hoja, pero también es la razón por la que una confirmación puede estar en más de una twig. 6 Estos nodos de hojas alcanzables nos llevan a los nodos alcanzables restantes, al igual que en Mercurial. Los nodos de hojas inalcanzables con grados en 0, después de agregar references externas, pueden eliminarse en cualquier momento. 7

El resultado es que al dibujar un Git DAG, podemos tener múltiples nombres de twigs apuntando a una confirmación, y podemos tener confirmaciones que (parecen) no tener nombres que los apunten. Vamos a decir más sobre esto más tarde. Por ahora, volvamos a la Figura 1.6 con Git en mente. Movemos los nombres de las twigs a la derecha, y cada nombre de twig apunta a la punta de esa twig. Para enfatizar que la position de un nodo de compromiso tiene poco que ver con qué twigs lo contienen, podemos dibujarlos en cualquier lugar conveniente. El nodo raíz está dentro de cada twig, por lo que no hay ninguna razón para preferir la fila labelda como master . Para mostrar cómo puede comprometer dos sugerencias de bifurcación diferentes al mismo time, o una confirmación de bifurcación puede ocurrir en medio de una cadena de compromiso, agregamos dos más nombres de bifurcación de Git: A apunta al mismo compromiso como master y B apunta a una confirmación en el medio de la release-v2 branch . (Estos nombres están destinados a ser ilustrativos, en lugar de útiles de inmediato, aunque A sería un buen lugar para comenzar el desarrollo de una nueva function que aún no está list para formar parte del master ).

Figura 2.9: variante de Git de la figura 1.6.

[Recorte muy grande aquí – tenga en count que el próximo bit incluye un poco de opinión, y puedo terminar rehaciéndolo un poco en el futuro. Ambas posturas tienen mérito: Git gana mucha flexibilidad con su sistema de ramificación efímera y ligero, pero definitivamente pierde algo en el process.]

Algunos usuarios argumentan que esto demuestra que Mercurial es superior a Git, porque siempre podemos rastrear compromisos individuales a twigs específicas. Algunos usuarios argumentan que esto demuestra lo contrario, por el mismo motivo, señalando que una statement como "commit 1417ae2 se hizo en hotfix " no tiene (o incluso tiene valor) negativo varios años después. De mala gana estoy de acuerdo con este último grupo, pero creo que esto hace que el uso de Git sea más difícil y propenso a errores al principio, porque los usuarios tienen nociones vagamente definidas de twigs, nociones vagas (si las hay) sobre DAG de compromiso, y no quieren tener que express subsets todo el time (ver la siguiente sección). Las twigs de Mercurial son inicialmente correctas, pero con el time, los nombres de las twigs se vuelven muy desorderados. La característica de cierre de twig de Mercurial, que oculta el nombre del uso normal, hace el truco inicialmente, pero el nombre de la twig oculta aún existe: debe devise un nombre nuevo (a menudo bastante incómodo) o reabrir la twig anterior, y esto es donde la vieja twig de repente tiene un valor negativo.


5 Existen varios commands de mantenimiento git que hacen esto y tardan un poco en ejecutarse en repositorys más grandes. Sin embargo, los usuarios normalmente nunca necesitan ejecutar esto por sí mismos.

6 Puede ser mejor pensar en compromisos contenidos en algunas twigs. Git tiene commands con --contains opciones para ver qué twigs y / o tags contienen confirmaciones particulares.

7 El recolector de basura de Git, o GC, realiza la eliminación. Obedece las reglas que protegen los artículos por un time, hasta que se hace reference o envejece, por lo que "en cualquier momento" no es del todo cierto. También puede desactivar el GC automático.