Listar tags en git repo orderadas por cómo aparecen en el gráfico

Dada una bifurcación y compromiso, quiero encontrar la primera label que trajo el compromiso dado.

Quiero escribir un script que haga esto.

No quiero imprimir todas las tags (que git log --tags --simplify-by-decoration ) pero solo las tags que aparecen entre la punta de la twig y la confirmación. Puedo usar las opciones --merged y --merged de git tag para eso pero imprime tags orderadas por nombres. Los necesito orderados de la forma en que aparecen en el gráfico (así que puedo hacer | tail -1 ) y no puedo hacer eso clasificándolos por nombres de campo como date de authordate , date de committerdate , creatordate , date de taggerdate .

Para dar más context, el script es la contraparte de este hilo SO de git-find-merge solo que el uso de las asignaciones de fusión para denotar el código PRD es un antipatrón .

Actualizar:

A continuación se muestra el guión que surgió finalmente de la respuesta de torek (github link: script de git-find-tag ).

~ / bin / git-find-tag:

 #!/bin/sh commit=$1 if [ -z $commit ]; then echo 1>&2 "fatal: commit is requinetworking" exit 1 fi commit=$(git rev-parse $commit) branch=${2-@} pattern=${3-.} # tags between branch and commit sorted as in graph following a pattern tags=$( git log --decorate --simplify-by-decoration --ancestry-path \ --pretty="format:%D" $commit..$branch \ | sed 's/, /\n/g' \ | grep '^tag: ' \ | sed 's/tag: //' \ | egrep "$pattern" ) if [ ! -z "$tags" ]; then echo "tags:" for tag in $tags; do echo " $tag" done echo "" fi tag=$(echo "$tags" | tail -1) if [ -z "$tag" ]; then # tag not found echo 1>&2 "fatal: no tag found" exit 1 fi git show -s "$tag" 

Parece que git log ya hace lo que quieres:

 git log --oneline --decorate --simplify-by-decoration --ancestry-path start..end 

Por ejemplo, ejecuté esto en el repository de Git para Git:

 $ git log --oneline --decorate --simplify-by-decoration --ancestry-path \ HEAD~20..HEAD b06d36431 (HEAD -> master, tag: v2.13.0, origin/master, origin/HEAD) Git 2.13 4fa66c85f (tag: v2.13.0-rc2) Git 2.13-rc2 027a3b943 (tag: v2.13.0-rc1) Git 2.13-rc1 

(tenga en count que no hay – ¡ --tags aquí!). Vea los detalles a continuación para una advertencia.

Detalles

El problema no es completamente resuelto en general, ya que no existe un order estrictamente definido en el que se emitirá el gráfico. Sabemos (a partir de la documentation) que --graph enciende --topo-sort ; pero hay charts en los que dos types topológicos diferentes son ambos válidos, como un diamante clásico:

  ... newer / child commits | D / \ BC \ / A older / parent commits | ... 

Las dos órdenes válidas aquí son (D, B, C, A) y (D, C, B, A) y no sabemos (a less que hagamos trampa 1 ) qué order usará git log . Si se labeln todos less A , el último será uno de (B, C), pero no sabemos cuál.

Si puede estar seguro de que no hay géneros ambiguos, la sugerencia de VonC de –contains, o una testing de git merge-base --is-ancestor , puede determinar si cualquier commit labeldo es un ancestro de cualquier otro commit labeldo. La definición de "order topológico" es "nunca mostrar a los niños después de mostrar al padre", es decir, lo que sea "la mayoría de los padres" es el que sale último.

Si no es así, y quiere hacer coincidir lo que hará el git log , tendrá que usar git log . Sin embargo, como ya hace lo que quieres, simplemente úsalo. 🙂 Te gustaría que:

  • Registre solo las --simplify-by-decoration labeldas: --simplify-by-decoration hace el trabajo, más o less, aunque también includeá nombres de sucursales (así que tenga cuidado con solo usar | tail -1 : necesita un poco más de sofisticación para poder tomar el último label, pero puede pasar por la grep tag: en el path).
  • Mostrar solo commits en o antes de un punto final ( end ) y después de un punto de inicio ( ^start ). Tenga en count que si desea include el punto de partida en sí, agregue el sufijo ^@ , que significa "todos los padres de la confirmación, pero no la confirmación".
  • Evite commits que no sean --ancestry-path de la confirmación de start : --ancestry-path hace el truco, excluyendo commits alcanzables desde end que no están ya excluidos por ^start .

start..end ^start end como el ^start end más familiar … start..end aquí, aunque funciona de cualquier manera.


1 La fuente de git log (con mucha dificultad) le dirá qué tipo realmente ocurre en estos casos.