Opción de remolques en git - opción bonita
Estaba tratando de extraer un resumen de las contribuciones de git log y crear un resumen conciso de eso y crear un excel / csv a partir de él para presentar informes.
lo intenté
git log --after="2020-12-10" --pretty=format:'"%h","%an","%ae","%aD","%s","(trailers:key="Reviewed By")"'
y el CSV se ve como con una columna CSV en blanco al final.
...
"7c87963cc","XYZ","[email protected]","Tue Dec 8 17:40:13 2020 +0000","[TTI] Add support for target hook in compiler.", ""
...
y se git log
ve algo como
commit 7c87963cc
Author: XYZ <[email protected]>
Date: Tue Dec 8 17:40:13 2020 +0000
[TTI] Add support for target hook in compiler.
This adds some code in the TabeleGen ...
This is my body of commit.
Reviewed By: Sushant
Differential Revision: https://codereviews.com/DD8822
Lo que no pude tener éxito fue extraer la Differential Revision
cadena usando el (trailers:key="Reviewed By")
comando.
No pude encontrar mucho sobre cómo hacer que esto funcione. Revisé el manual de git y probé lo que explica.
¿Hay algo que pueda faltar en este comando? La salida esperada debe tener el texto https://codereviews.com/DD8822
en la última posición en la salida CVS anterior.
Respuestas
No estoy seguro pero:
- las claves de avance no pueden tener espacios en blanco (por lo tanto
Reviewed By
->Reviewed-By
yDifferential Revision
->Differential-Revision
); - Los trailers no deben estar delimitados por nuevas líneas, sino separados del mensaje de confirmación de confirmación (por lo tanto,
Reviewed By
su pregunta no se considera un avance).
Tampoco recomendaría usar CSV, pero usar TSV en su lugar: la salida de git no es consciente de la sintaxis de CSV (punto y coma y comas que se escapan), por lo tanto, el documento de salida puede generarse no se puede analizar.
Si sus mensajes de confirmación se verían así (en -
lugar de espacios, sin nuevos delimitadores de línea):
commit 7c87963cc
Author: XYZ <[email protected]>
Date: Tue Dec 8 17:40:13 2020 +0000
[TTI] Add support for target hook in compiler.
This adds some code in the TabeleGen ...
This is my body of commit.
Reviewed-By: Sushant
Differential-Revision: https://codereviews.com/DD8822
Entonces el siguiente comando funcionaría para usted:
git log --pretty=format:'%h%x09%an%x09%ae%x09%aD%x09%s%x09%(trailers:key=Reviewed-By,separator=%x20,valueonly)%x09%(trailers:key=Differential-Revision,separator=%x20,valueonly)'
produciendo un ID de confirmación corto, nombre de autor, correo electrónico del autor, fecha, mensaje de confirmación, avance Reviewed-By
y avance Differential-Revision
para su salida de valores separados por tabulaciones.
Si usted no puede cambiar la vieja mensajes de confirmación debido a que su historia no es seguro para hacer esto (que se haya publicado, tirado por pares, sus herramientas están unidos a los hashes publicados commit), entonces usted tiene que procesar la git log
salida con sed
, awk
, perl
, o cualquier otra herramienta de transformación de texto para generar su informe. Digamos, procese algo como git log --pretty=format:'%x02%h%x1F%an%x1F%ae%x1F%aD%x1F%s%x1F%n%B'
dónde las líneas entre ^B
(STX) y EOF deben analizarse de alguna manera (filtrar los trailers que le interesan), luego unirse a sus líneas de grupo comenzando con ^B
, y luego reemplazar el carácter para reemplazar los separadores de campo y entrada con \t
y no personaje respectivamente.
Pero nuevamente, si puede editar el historial arreglando los avances de los mensajes de confirmación (no estoy seguro de cuánto puede afectar), le recomiendo que lo haga y luego rechace la idea de scripts adicionales que procesan los avances que no son reconocidos por git-interpret-trailers
y simplemente corrija el cometer mensajes.
Editar 1 (herramientas de texto)
Si reescribir el historial no es una opción, entonces implementar algunos scripts puede ayudarlo. Estoy bastante débil en la escritura de gran alcance sed
/ awk
/ perl
guiones, pero voy a tratar de.
git log --pretty=format:'%x02%h%x1F%an%x1F%ae%x1F%aD%x1F%s%x1F%n%B' \
| gawk -f trailers.awk \
| sed '$!N;s/\n/\x1F/' \
| sed 's/[\x02\x1E]//g' \
| sed 's/\x1F/\x09/g'
Cómo funciona:
git
genera un registro hecho de datos delimitados con códigos C0 C1 estándar asumiendo que no hay tales caracteres en sus mensajes de confirmación (STX, RS y US - realmente no sé si es un buen lugar para usarlos así y si los aplico semánticamente correcto);gawk
filtra la salida del registro tratando de analizar los grupos iniciados por STX y extraer los avances, generando una salida de "dos filas" (cada línea impar para datos regulares, cada línea par para valores de avance unidos por comas incluso para avances faltantes);sed
une líneas pares e impares por pares (los créditos van para Karoly Horvath );sed
elimina STX y RS;sed
reemplaza US a TAB.
Aquí está el trailers.awk
(de nuevo, no soy un awk
chico y no tengo idea de lo idiomático que es el siguiente script, pero parece funcionar):
#!/usr/bin/awk -f
BEGIN {
FIRST = 1
delete TRAILERS
}
function print_joined_array(array) {
if ( !length(array) ) {
return
}
for ( i in array ) {
if ( i > 0 ) {
printf(",")
}
printf("%s", array[i])
}
printf("\x1F")
}
function print_trailers() {
if ( FIRST ) {
FIRST = 0
return
}
print_joined_array(TRAILERS["Reviewed By"])
print_joined_array(TRAILERS["Differential Revision"])
print ""
}
/^\x02/ {
print_trailers()
print $0
delete TRAILERS
}
match($0, /^([-_ A-Za-z0-9]+):\s+(.*)\s*/, M) {
TRAILERS[M[1]][length(TRAILERS[M[1]])] = M[2]
}
END {
print_trailers()
}
Un par de palabras sobre cómo funciona el awk
guión:
- asume que los registros que no requieren procesamiento comienzan con STX;
- intenta
grep
buscar unKey Name: Value
patrón en cada línea que no sea "STX" y guarda el resultado encontrado en una matriz temporalTRAILERS
(que en realidad sirve como un multimapa, comoMap<String, List<String>>
en Java) para cada registro; - cada registro se escribe como está, pero los avances se escriben antes de detectar un nuevo registro o en EOF.
Editar 2 (mejor awk
)
Bueno, soy realmente débil awk
, así que una vez que leí más sobre awk
las variables internas, descubrí que el awk
script se puede volver a implementar por completo y producir una salida similar a TSV lista para usar sin ningún procesamiento posterior con sed
o perl
. Entonces, la versión más corta y mejorada del script es:
#!/bin/bash
git log --pretty=format:'%x1E%h%x1F%an%x1F%ae%x1F%aD%x1F%s%x1F%B%x1E' \
| gawk -f trailers.awk
#!/usr/bin/awk -f
BEGIN {
RS = "\x1E"
FS = "\x1F"
OFS = "\x09"
}
function extract(array, trailer_key, __buffer) {
for ( i in array ) {
if ( index(array[i], trailer_key) > 0 ) {
if ( length(__buffer) > 0 ) {
__buffer = __buffer ","
}
__buffer = __buffer substr(array[i], length(trailer_key))
}
}
return __buffer
}
NF > 1 {
split($6, array, "\n")
print $1, $2, $3, $4, $5, extract(array, "Reviewed By: "), extract(array, "Differential Revision: ")
}
Mucho más conciso, más fácil de leer, comprender y mantener.