Anhänger Option in Git - hübsche Option
Ich habe versucht, eine Zusammenfassung der Beiträge aus dem Git-Protokoll zu extrahieren, eine kurze Zusammenfassung davon zu erstellen und daraus ein Excel / CSV zu erstellen, um Berichte zu präsentieren.
Ich habe es versucht
git log --after="2020-12-10" --pretty=format:'"%h","%an","%ae","%aD","%s","(trailers:key="Reviewed By")"'
und die CSV sieht aus wie mit einer leeren CSV-Spalte am Ende.
...
"7c87963cc","XYZ","[email protected]","Tue Dec 8 17:40:13 2020 +0000","[TTI] Add support for target hook in compiler.", ""
...
und das git log
sieht so aus wie
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
Was mir nicht gelingen konnte, war das Extrahieren der Differential Revision
Zeichenfolge mit dem (trailers:key="Reviewed By")
Befehl.
Ich konnte nicht viel darüber finden, wie ich das zum Laufen bringen kann. Ich habe das Git-Handbuch überprüft und versucht, was es erklärt.
Gibt es etwas, das mir in diesem Befehl fehlen könnte? Die erwartete Ausgabe sollte den Text https://codereviews.com/DD8822
an der letzten Position in der obigen CVS-Ausgabe haben.
Antworten
Ich bin mir aber nicht sicher:
- Trailer-Schlüssel dürfen keine Leerzeichen haben (daher
Reviewed By
->Reviewed-By
undDifferential Revision
->Differential-Revision
); - Trailer sollten nicht durch neue Zeilen begrenzt, sondern von der Commit-Commit-Nachricht getrennt werden (daher wird
Reviewed By
Ihre Frage nicht als Trailer betrachtet).
Ich würde auch nicht empfehlen, CSV zu verwenden, sondern stattdessen TSV: Die Git-Ausgabe kennt die CSV-Syntax nicht (Semikolons und Kommas werden ausgeblendet), daher wird das Ausgabedokument möglicherweise nicht analysierbar generiert.
Wenn Ihre Commit-Nachrichten so aussehen würden ( -
anstelle von Leerzeichen keine neuen Zeilenbegrenzer):
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
Dann würde der folgende Befehl für Sie funktionieren:
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)'
Erstellen einer kurzen Festschreibungs-ID, eines Autorennamens, einer E-Mail-Adresse des Autors, eines Datums, einer Festschreibungsnachricht, eines Trailers Reviewed-By
und eines Trailers Differential-Revision
für Ihre durch Tabulatoren getrennte Werte.
Wenn Sie nicht die alten Nachrichten begehen kann sich ändern , weil Ihre Geschichte nicht sicher ist , dies zu tun (es ist veröffentlicht, von Kollegen gezogen, Ihre Werkzeuge sind auf die veröffentlichten verpflichten Hashes gebunden ist ), dann müssen Sie den Prozess - git log
Ausgang mit sed
, awk
, perl
oder jede anderes Texttransformationswerkzeug zum Generieren Ihres Berichts. Verarbeiten Sie beispielsweise, git log --pretty=format:'%x02%h%x1F%an%x1F%ae%x1F%aD%x1F%s%x1F%n%B'
wo Linien zwischen ^B
(STX) und EOF irgendwie analysiert werden sollten (gefiltert nach den Anhängern, an denen Sie interessiert sind), dann beginnend mit ihren Gruppenlinien verbunden ^B
werden und dann das Zeichen ersetzt werden, um Feld- und Eintragstrennzeichen durch \t
und nein zu ersetzen Zeichen jeweils.
Wenn Sie jedoch den Verlauf bearbeiten können, indem Sie Commit-Nachrichten-Trailer reparieren (nicht sicher, wie stark sich dies auswirken kann), würde ich Ihnen empfehlen, dies zu tun und dann die Idee von zusätzlichen Skripten, die Trailer verarbeiten, die von nicht erkannt werden, abzulehnen git-interpret-trailers
und einfach die zu reparieren Nachrichten festschreiben.
Bearbeiten 1 (Textwerkzeuge)
Wenn das Umschreiben des Verlaufs nicht möglich ist, kann die Implementierung einiger Skripte hilfreich sein. Ich bin mir ziemlich schwach auf das Schreiben mächtig sed
/ awk
/ perl
Skripte, aber lassen Sie mich versuchen.
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'
Wie es funktioniert:
git
generiert ein Protokoll aus Daten, die mit Standard- C0-C1-Codes abgegrenzt sind, vorausgesetzt, Ihre Commit-Nachrichten enthalten keine solchen Zeichen (STX, RS und US - ich weiß nicht wirklich, ob es ein guter Ort ist, sie so zu verwenden, und ob ich sie anwende semantisch korrekt);gawk
filtert die Protokollausgabe, die versucht, STX-gestartete Gruppen zu analysieren und die Trailer zu extrahieren, wodurch eine "zweireihige" Ausgabe generiert wird (jede ungerade Zeile für reguläre Daten, jede gerade Zeile für durch Kommas verbundene Trailerwerte, selbst für fehlende Trailer);sed
verbindet ungerade und gerade Linien paarweise (Credits gehen an Karoly Horvath );sed
entfernt STX und RS;sed
ersetzt US durch TAB.
Hier ist das trailers.awk
(wieder bin ich kein awk
Typ und habe keine Ahnung, wie idiomatisch das folgende Skript ist, aber es scheint zu funktionieren):
#!/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()
}
Ein paar Worte, wie das awk
Skript funktioniert:
- Es wird davon ausgegangen, dass Datensätze, die nicht verarbeitet werden müssen, mit STX beginnen.
- Es versucht, für
grep
jedesKey Name: Value
Muster in jeder Nicht-STX-Zeile ein Muster zu finden und speichert das gefundene Ergebnis für jeden Datensatz in einem temporären ArrayTRAILERS
(das tatsächlich als Multimap dient, wieMap<String, List<String>>
in Java). - Jeder Datensatz wird so geschrieben, wie er ist, aber Trailer werden entweder vor dem Erkennen eines neuen Datensatzes oder bei EOF geschrieben.
Edit 2 (besser awk
)
Nun, ich bin sehr schwach darin. awk
Nachdem ich mehr über awk
interne Variablen gelesen hatte , stellte ich fest, dass das awk
Skript vollständig neu implementiert werden kann und eine gebrauchsfertige TSV-ähnliche Ausgabe selbst ohne Nachbearbeitung mit sed
oder erzeugt werden kann perl
. Die kürzere und verbesserte Version des Skripts lautet also:
#!/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: ")
}
Viel prägnanter, leichter zu lesen, zu verstehen und zu warten.