Puede obtener esto casi directamente en git rev-list
.
latest.awk
:
BEGIN { thiscommit=""; }
$1 == "commit" {
if (thiscommit != "")
print thiscommit, tags[thiscommit]
thiscommit=$2
line[$2]=NR
latest = 0;
for (i = 3 ; i <= NF ; ++i) if (line[$i] > latest) {
latest = line[$i];
tags[$2] = tags[$i];
}
next;
}
$1 != "commit" { tags[thiscommit] = $0; }
END { if (thiscommit != "") print thiscommit, tags[thiscommit]; }
un comando de ejemplo:
git rev-list --date-order --children --format=%d --all | awk -f latest.awk
también se puede utilizar --topo-order
, y es probable que tenga que eliminar a los árbitros no deseados en la lógica $1!="commit"
.
Dependiendo del tipo de transitividad que desee y de lo explícito que sea el listado, la acumulación de las etiquetas puede necesitar un diccionario. Aquí hay una que recibe una lista explícita de todas las referencias para todas las confirmaciones:
all.awk
:
BEGIN {
thiscommit="";
}
$1 == "commit" {
if (thiscommit != "")
print thiscommit, tags[thiscommit]
thiscommit=$2
line[$2]=NR
split("",seen);
for (i = 3 ; i <= NF ; ++i) {
nnew=split(tags[$i],new);
for (n = 1 ; n <= nnew ; ++n) {
if (!seen[new[n]]) {
tags[$2]= tags[$2]" "new[n]
seen[new[n]] = 1
}
}
}
next;
}
$1 != "commit" {
nnew=split($0,new,", ");
new[1]=substr(new[1],3);
new[nnew]=substr(new[nnew],1,length(new[nnew])-1);
for (n = 1; n <= nnew ; ++n)
tags[thiscommit] = tags[thiscommit]" "new[n]
}
END { if (thiscommit != "") print thiscommit, tags[thiscommit]; }
all.awk
tomó unos minutos para hacer el kernel de linux repo 322K compromete, alrededor de un millar de un segundo o algo por el estilo (muchas cadenas duplicadas y procesamiento redundante) por lo que probablemente quieras volver a escribir eso en C++ si realmente buscas el producto cruzado completo ... pero no creo que gitk lo demuestre, solo los vecinos más cercanos, a la derecha ?
¿Sería útil implementar su propia funcionalidad de caché cli? Si es así, creo que puedo aportar algunas ideas para eso. –
Sí, eso funcionaría para mí. – leco