Tengo que crear una revisión del código de las twigs no fusionadas.
Nota al margen: al encontrar soluciones, no vayamos al problema del context de la sucursal local, ya que esto se ejecutará en un server, solo habrá un origen remoto, siempre ejecutaré un command de origen de búsqueda de git antes de otros commands y cuando hablemos sobre twigs, nos referiremos al origen / nombre-twig .
Nota al margen 2: Tengo buen conocimiento de cómo funciona git tanto en porcelana como en fontanería.
Si la configuration fuera simple y cada twig que se originó desde el maestro continuaría en su propio path, podríamos simplemente ejecutar:
git rev-list origin/branch-name --not origin/master --no-merges
para cada twig no fusionada y agregue las confirmaciones resultantes a cada revisión por twig.
El problema surge cuando hay una fusión entre 2-3 twigs y el trabajo continuo en algunas de ellas. Como dije, para cada sucursal quiero crear revisiones programáticas programáticas y no quiero include una confirmación en múltiples revisiones.
Principalmente los problemas se networkingucen al encontrar la twig original para cada compromiso.
O para simplificar … encontrar todas las asignaciones no fusionadas agrupadas por la twig en la que probablemente fueron creadas.
Centrémonos en un simple ejemplo:
- * b4 - branch2's head * | a4 - branch1's head | * b3 * | merge branch2 into branch1 * |\ | m3 - master's head | * \| a3 | | | | | * b2 | * | merge master into branch1 * /| | m2 |/ | * merge branch1 into branch2 | * /| a2 | |/ | | | * b1 | | / | |/ | /| |/ | | * a1 * / m1 |/ | * start -
y lo que quiero get es:
La mejor solución que he encontrado hasta ahora es ejecutar:
git show-branch --topo-order --topics origin/master origin/branch1 origin/branch2
y analizar el resultado:
* [master] m3 ! [branch1] a4 ! [branch2] b4 --- + [branch2] b4 + [branch2^] b3 + [branch1] a4 ++ [branch2~2] b2 -- [branch2~3] Merge branch 'branch1' into branch2 ++ [branch2~4] b1 + [branch1~2] a3 + [branch1~4] a2 ++ [branch1~5] a1 *++ [branch2~5] m1
La interpretación de salida es así:
Para el punto 3. la resolución del nombre de confirmación comienza con un nombre de twig y, a partir de lo que veo, esta twig corresponde a la confirmación de la twig en la que se creó, probablemente al promover la ruta que llega al primer padre.
Como no estoy interesado en fusionar compromisos, los ignoraré.
Luego analizaré cada branch-path-commit para get su hash con rev-parse.
¿Alguien tiene alguna idea programática mejor para resolver esto?
El repository se puede clonar con --mirror
que crea un repository vacío que se puede usar como un espejo del repository original y se puede actualizar con git remote update --prune
después de lo cual todas las tags se deben eliminar para esta function.
Lo implemento de esta manera:
1. get una list de twigs no fusionadas en el maestro
git branch --no-merged master
2. para cada twig, obtenga una list de revisiones en esa twig y no en la twig principal
git rev-list branch1 --not master --no-merges
Si la list está vacía, elimine la twig de la list de twigs
3. Para cada revisión, determine la twig original con
git name-rev --name-only revisionHash1
y coincide con la expresión regular para ^([^\~\^]*)([\~\^].*)?$
. El primer patrón es el nombre de la twig, el segundo es la ruta relativa a la twig.
Si el nombre de la twig encontrada no es igual a la twig inicial, elimine la revisión de la list.
Al final obtuve una list de twigs y para cada una de ellas una list de confirmaciones.
Después de investigar un poco más, se puede hacer todo en una sola línea con:
git rev-list --all --not master --no-merges | xargs -L1 git name-rev | grep -oE '[0-9a-f]{40}\s[^\~\^]*'
El resultado es un resultado en forma
hash branch
que se puede leer, analizar, orderar, agrupar o lo que sea.
Si capto su espacio problemático, creo que puede usar –sha1-name
git show-branch –topo-order –topics –sha1-name origen / master origin / branch1 origin / branch2
para enumerar lo que le interesa, luego ejecute los commits a través de git-what-branch
git-what-branch : Descubre en qué twig está una confirmación, o cómo llegó a una twig con nombre. Este es un script Perl de Seth Robertson
y formatee el informe según sus necesidades?
No hay una respuesta correcta a esta pregunta porque está poco especificada.
La historia de Git es simplemente un gráfico acíclico dirigido (DAG), y en general es imposible determinar las relaciones semánticas entre dos nodos arbitrarios en un DAG a less que los nodos estén suficientemente labeldos. A less que pueda garantizar que los posts de confirmación en su gráfico de ejemplo siguen un patrón confiable, que puede analizarse por máquina, las confirmaciones no están suficientemente labeldas; es imposible identificar automáticamente las confirmaciones que le interesan sin context adicional (por ejemplo, garantías que sus desarrolladores siguen ciertas mejores prácticas).
Aquí hay un ejemplo de lo que quiero decir. Usted dice que commit a1
está asociado con branch1
, pero esto no puede determinarse con certeza simplemente mirando los nodos de su gráfico de ejemplo. Es posible que alguna vez tu historial de repositorys de ejemplo fuera así:
* merge branch1 into branch2 - branch2's head |\ _|/ / * b1 | | | | _|_/ / | | * a1 * / m1 |/ | * start - master's head
Tenga en count que branch1
ni siquiera existe en el gráfico anterior. El gráfico anterior podría haber surgido de la siguiente secuencia de events:
branch2
se crea al start
en el repository compartido a1
en su twig branch2
local m1
y b1
en su twig branch2
local branch2
local en el repository compartido, lo que hace que la reference de branch2
en el repository compartido apunte a a1
branch2
local al repository compartido, pero esto falla con un error de avance rápido ( branch2
actualmente apunta a a1
y no se puede reenviar rápidamente a b1
) git pull
, fusionando a1
en b1
git commit --amend -m "merge branch1 into branch2"
por alguna razón inexplicable Algún time después, el usuario n. ° 1 crea branch1
fuera de a1
y crea a2
, mientras que el usuario n. ° 2 de avance rápido fusiona m1
en master
, lo que da como resultado el siguiente historial de confirmaciones:
* merge a1 into b1 - branch2's head * |\ a2 - branch1's head | _|/ |/ * b1 | | | | _|_/ / | | * a1 * / m1 - master's head |/ | * start
Dado que esta secuencia de events es técnicamente posible (aunque poco probable), ¿cómo puede un humano dejar que Git le diga cuál se compromete a "pertenecer" a qué twig?
Si puede garantizar que los usuarios no cambien los posts de confirmación de fusión (siempre aceptan el valor pnetworkingeterminado de Git), y que Git nunca y nunca cambiará el formatting de post de confirmación de combinación pnetworkingeterminada, entonces el post de confirmación de la fusión se puede usar como pista que a1
comenzó en branch1
. Tendrá que escribir una secuencia de commands para analizar los posts de confirmación; no hay simples lineamientos de Git para hacer esto por usted.
Alternativamente, si tus desarrolladores siguen las mejores prácticas (cada fusión es intencional y está destinada a include una twig de nombre diferente, lo que da como resultado un repository sin esas estúpidas confusiones de fusión creadas por git pull
), y no estás interesado en las confirmaciones de un sucursal hija completa, entonces las confirmaciones que le interesan están en la ruta del primer padre. Si sabe qué sucursal es el padre de la sucursal que está parsing, puede hacer lo siguiente:
git rev-list --first-parent --no-merges parent-branch-ref..branch-ref
Este command enumera los identificadores SHA1 para las confirmaciones a las que se puede acceder desde branch-ref
excluyendo las confirmaciones accesibles desde parent-branch-ref
y las confirmaciones que se combinaron desde las twigs secundarias.
En el gráfico de ejemplo anterior, suponiendo que el order principal está determinado por sus annotations y no por el order de las líneas que entran en un compromiso de fusión, git rev-list --first-parent --no-merges master..branch1
imprimiría el SHA1 identificadores para commits a4, a3, a2 y a1 (en ese order; use --reverse
si quiere el order opuesto), y git rev-list --first-parent --no-merges master..branch2
imprimiría el Identificadores SHA1 para confirmaciones b4, b3, b2 y b1 (nuevamente, en ese order).
Si tus desarrolladores no siguen las mejores prácticas y tus sucursales están llenas de esas estúpidas fusiones creadas por git pull
(u otra operación equivalente), pero tienes claras las relaciones entre padres e hijos, entonces escribir un script para ejecutar el siguiente algorithm puede funcionar para tú:
Encuentre todas las confirmaciones accesibles desde la twig de interés, excluyendo todas las confirmaciones de su sucursal principal, la sucursal principal de sus padres, la sucursal principal de sus padres, etc., y guarde los resultados. Por ejemplo:
git rev-list master..branch1 >commit-list
Haga lo mismo para todas las twigs de niños, nietos, etc. de la twig de interés. Por ejemplo, suponiendo que branch2
se considera hijo de branch1
:
git rev-list ^master ^branch1 branch2 >commits-to-filter-out
Filtra los resultados del paso # 2 de los resultados del paso # 1. Por ejemplo:
grep -Fv -f commits-to-filter-out commit-list
El problema con este enfoque es que una vez que una sucursal hija se fusiona con su principal, se considera que esas confirmaciones son parte del padre, incluso si el desarrollo en la sucursal de hijo continúa. Aunque esto tiene sentido semánticamente, no produce el resultado que usted dice que quiere.
Estas son algunas de las mejores prácticas para hacer que este problema en particular sea más fácil de resolver en el futuro. La mayoría, si no todos, se pueden aplicar a través del uso inteligente de los ganchos en el repository compartido.
git pull
--no-ff
. Si tiene twigs secundarias, aún puede volver a establecer la base, pero conserve las fusiones --no-ff
de las twigs secundarias (esto es más complicado de lo que debería ser). Si todos tus desarrolladores siguen estas reglas, entonces un simple:
git rev-list --first-parent --no-merges parent-branch..child-branch
es todo lo que necesita para ver las confirmaciones que se realizaron en esa twig less los compromisos realizados en las twigs de sus hijos.
Sugeriría hacerlo de la manera en que lo describiste. Pero trabajaría en la salida de git log --format="%H:%P:%s" ^origin/master origin/branch1 origin/branch2
, por lo que puede hacer mejor andar en tree.
git rev-parse
). Marque cada compromiso con los nombres de la cabeza de donde vino y su distancia.
commit -> known-name
. Ahora, para cada una de sus confirmaciones, tendrá una list de valores de distancia (que podrían ser negativos) para las cabezas de sucursal. Para cada compromiso, la twig con la menor distancia es en la que probablemente se creó el compromiso.
Si tiene time, es posible que desee recorrer toda la historia y luego restar la historia de la maestría, que podría dar resultados ligeramente mejores si sus twigs se han fusionado en el maestro antes.
No pude resistir: hice un script de Python que hace lo que describí. Pero con un cambio: con cada paso normal, la distancia no aumenta, sino que disminuye. Esto tiene el efecto de que las twigs que vivieron más time después de un punto de fusión son preferidas, lo que personalmente me gusta más. Aquí está: https://gist.github.com/Chronial/5275577
Uso: simplemente ejecute git-annotate-log.py ^origin/master origin/branch1 origin/branch2
verifique la calidad de los resultados (generará un tree de logging git con annotations).