Wie man ‘git diff’ dazu bringt, Kommentare zu ignorieren
Lesezeit: 9 Minuten
Benuvogel
Ich versuche, eine Liste der Dateien zu erstellen, die in einem bestimmten Commit geändert wurden. Das Problem ist, dass jede Datei die Versionsnummer in einem Kommentar am Anfang der Datei hat – und da dieser Commit eine neue Version einführt, bedeutet das das Jede Datei hat sich geändert.
Die geänderten Kommentare sind mir egal, also hätte ich sie gerne git diff Ignorieren Sie alle übereinstimmenden Zeilen ^s**.*$da dies alles Kommentare sind (Teil von /* */).
Ich kann keine Möglichkeit finden, das zu sagen git diff bestimmte Zeilen zu ignorieren.
Ich habe bereits versucht, ein textconv-Attribut zu setzen, um Git dazu zu bringen, die Dateien an sed zu übergeben, bevor es sie unterscheidet, damit sed die anstößigen Zeilen entfernen kann – das Problem dabei ist das git diff --name-status unterscheidet die Dateien nicht wirklich, sondern vergleicht nur die Hashes, und natürlich haben sich alle Hashes geändert.
Gibt es eine Möglichkeit, dies zu tun?
Eine wilde Vermutung … Hast du es versucht? git diff --name-status --textconv? Oder vielleicht git diff --name-only?
– rodrigo
13. Mai ’13 um 16:55 Uhr
Ja, ich verwende –name-only, aber es gibt (wie gesagt) jede Datei zurück, weil bei jeder Datei die Kommentare geändert wurden. –textconv funktioniert nicht, weil, wie ich auch im Beitrag sagte, git es ignoriert, wenn es kein vollständiges Diff erzeugt.
– Benuvogel
13. Mai 13 um 17:04 Uhr
mögliches Duplikat des Ignorierens von Änderungen, die mit einer Zeichenfolge in git diff übereinstimmen
– richvdh
23. Juni 15 um 14:08 Uhr
@richvdh Ich denke, die Fragen sind ähnlich genug, um als Duplikat betrachtet zu werden, ABER sie haben unterschiedliche richtige Antworten, und diese Frage enthält zusätzliche Antworten, die Vorschläge machen, die das andere Q nicht hat, daher glaube ich, dass es sinnvoll ist, beide zu behalten.
– Benuvogel
23. Juni 15 um 15:23 Uhr
Verwandte: Git 2.30 (Q1 2021) wird vorschlagen git diff -I<regex>.
– VonC
9. November 20 um 20:16 Uhr
phyatt
Hier ist eine Lösung, die für mich gut funktioniert. Ich habe die Lösung und einige zusätzliche fehlende Dokumentationen aufgeschrieben git (log|diff) -G<regex> Möglichkeit.
Es wird im Grunde dieselbe Lösung wie in den vorherigen Antworten verwendet, jedoch speziell für Kommentare, die mit a beginnen * oder ein #und manchmal ein Leerzeichen vor dem *… Aber es muss noch zulassen #ifdef, #includeetc. Änderungen.
Der Blick nach vorn und der Blick nach hinten scheinen von dem nicht unterstützt zu werden -G Option noch die ? im Allgemeinen, und ich hatte Probleme mit der Verwendung *auch. + scheint aber gut zu funktionieren.
(Hinweis, getestet auf Git v2.7.0)
Mehrzeilige Kommentarversion
git diff -w -G'(^[^*# /])|(^#w)|(^s+[^*#/])'
-w Leerzeichen ignorieren
-G nur Diff-Zeilen anzeigen, die mit der folgenden Regex übereinstimmen
(^[^*# /]) jede Zeile, die nicht mit einem Stern, einer Raute oder einem Leerzeichen beginnt
(^#w) jede Zeile, die mit beginnt # gefolgt von einem Buchstaben
(^s+[^*#/]) jede Zeile, die mit einem Leerzeichen beginnt, gefolgt von einem Kommentarzeichen
Grundsätzlich ändert ein SVN-Hook jetzt jede Datei ein und aus und modifiziert mehrzeilige Kommentarblöcke in jeder Datei. Jetzt kann ich meine Änderungen mit SVN ohne die FYI-Informationen vergleichen, die SVN in den Kommentaren ablegt.
Technisch ermöglicht dies Python- und Bash-Kommentare wie #TODO im Diff angezeigt werden, und wenn ein Divisionsoperator in C++ in einer neuen Zeile beginnt, kann er ignoriert werden:
a = b
/ c;
Auch die Dokumentation auf -G in Git schien ziemlich mangelhaft zu sein, daher sollten die Informationen hier helfen:
git diff -G<regex>
-G<regex>
Suchen Sie nach Unterschieden, deren Patch-Text hinzugefügte/entfernte Zeilen enthält, die übereinstimmen <regex>.
Um den Unterschied zwischen zu veranschaulichen -S<regex> --pickaxe-regex und -G<regex>betrachten Sie einen Commit mit dem folgenden Unterschied in derselben Datei:
Während git log -G"regexec(regexp" wird dieses Commit zeigen, git log -S"regexec(regexp" --pickaxe-regex nicht (da sich die Anzahl der Vorkommen dieser Zeichenfolge nicht geändert hat).
Siehe die Spitzhacke Eintrag ein gitdiffcore(7) für mehr Informationen.
(Hinweis, getestet auf Git v2.7.0)
-G verwendet einen einfachen regulären Ausdruck.
Keine Unterstützung für ?, *, !, {, } Syntax regulärer Ausdrücke.
Gruppieren mit () und ODER-Gruppen arbeitet mit |.
Platzhalterzeichen wie z s, Wusw. werden unterstützt.
Look-Ahead und Look-Behind sind nicht unterstützt.
Anfangs- und Endlinienanker ^$ arbeiten.
Feature ist seit Git 1.7.4 verfügbar.
Ausgeschlossene Dateien v Ausgeschlossene Unterschiede
Notiere dass der -G Option filtert die Dateien, die verglichen werden.
Aber wenn eine Datei “verschieden” wird, werden die Zeilen, die vorher “ausgeschlossen/eingeschlossen” waren, auch alle im Diff angezeigt werden.
Beispiele
Zeige nur Dateiunterschiede mit mindestens einer Zeile, die erwähnt foo.
git diff -G'foo'
Dateiunterschiede für alles außer Zeilen anzeigen, die mit a beginnen #
git diff -G'^[^#]'
Dateien anzeigen, die Unterschiede aufweisen FIXME oder TODO
if (opts & (DIFF_PICKAXE_REGEX | DIFF_PICKAXE_KIND_G)) {
int cflags = REG_EXTENDED | REG_NEWLINE;
if (DIFF_OPT_TST(o, PICKAXE_IGNORE_CASE))
cflags |= REG_ICASE;
regcomp_or_die(®ex, needle, cflags);
regexp = ®ex;
// and in the regcom_or_die function
regcomp(regex, needle, cflags);
REG_EXTENDED
Use POSIX Extended Regular Expression syntax when interpreting
regex. If not set, POSIX Basic Regular Expression syntax is
used.
// …
REG_NEWLINE
Match-any-character operators don't match a newline.
A nonmatching list ([^...]) not containing a newline does not
match a newline.
Match-beginning-of-line operator (^) matches the empty string
immediately after a newline, regardless of whether eflags, the
execution flags of regexec(), contains REG_NOTBOL.
Match-end-of-line operator ($) matches the empty string
immediately before a newline, regardless of whether eflags
contains REG_NOTEOL.
Das kann nicht ganz richtig sein, da es eine nicht einfache Syntax akzeptiert, wie z + (Habe ich gerade getestet).
– Emadpres
24. April 17 um 13:18 Uhr
Siehe Update am Ende meiner Antwort. Ich habe die “POSIX erweiterten regulären Ausdrücke” nicht erfolgreich getestet. Meine empirischen Tests haben gezeigt, dass es nicht ganz gleich funktioniert.
– phyatt
24. April 17 um 13:51 Uhr
@phyatt – das scheint nicht zu funktionieren: git diff -G'^[^#]'. Es zeigt immer noch Zeilen, die mit beginnen #.
– Martin Vegetar
24. August 19 um 5:54 Uhr
@MartinVegter Die Syntax wird weiterhin angezeigt, wenn die Datei mindestens einen weiteren Unterschied aufweist. Wenn eine Datei nur Kommentarunterschiede aufweist, wird die Datei in den Ergebnissen ausgeschlossen.
– phyatt
24. August 19 um 12:17 Uhr
Riezebosch
git diff -G <regex>
Und geben Sie einen regulären Ausdruck an, der dies tut nicht mit Ihrer Versionsnummernzeile übereinstimmen.
richvdh
Ich fand es am einfachsten zu bedienen git difftool So starten Sie ein externes Diff-Tool:
git difftool -y -x "diff -I '<regex>'"
Benuvogel
Ich habe eine Lösung gefunden. Ich kann diesen Befehl verwenden:
git diff --numstat --minimal <commit> <commit> | sed '/^[1-]s+[1-]s+.*/d'
Um die Dateien anzuzeigen, bei denen sich zwischen Commits mehr als eine Zeile geändert hat, wodurch Dateien eliminiert werden, deren einzige Änderung die Versionsnummer in den Kommentaren war.
Nur Kommentarzeilenänderungen können berechnet werden. (EIN)
Verwenden der Ausgabe von ‘git diff –stat’,
git diff -w --stat
alle Linienänderungen können berechnet werden. (B)
Um die Anzahl der nicht kommentierten Quellzeilenänderungen (NCSL) zu erhalten, subtrahieren Sie (A) von (B).
Erläuterung:
In der ‘git diff’-Ausgabe (in der Leerzeichenänderungen ignoriert werden),
Achten Sie auf eine Zeile, die entweder mit „+“ oder „-“ beginnt, was eine geänderte Zeile bedeutet.
Darauf können optionale Leerzeichen folgen. ‘S*’
Suchen Sie dann nach dem Kommentarzeilenmuster ‘/*’ (oder) einfach ‘*’ (oder) ‘//’.
Da die Option ‘-c’ mit grep angegeben wird, geben Sie einfach die Anzahl aus. Entfernen Sie die Option ‘-c’, um nur die Kommentare in den Diffs zu sehen.
HINWEIS: Aufgrund der folgenden Annahmen kann es zu geringfügigen Fehlern bei der Anzahl der Kommentarzeilen kommen, und das Ergebnis sollte als Richtwert angesehen werden.
1.) Quelldateien basieren auf der C-Sprache. Makefile- und Shell-Skriptdateien haben eine andere Konvention, ‘#’, um die Kommentarzeilen zu kennzeichnen, und wenn sie Teil von diffset sind, werden ihre Kommentarzeilen nicht gezählt.
2.) Die Git-Konvention der Zeilenänderung: Wenn eine Zeile geändert wird, sieht Git dies so, als ob diese bestimmte Zeile gelöscht und dort eine neue Zeile eingefügt wird, und es kann so aussehen, als würden zwei Zeilen geändert, während in Wirklichkeit eine Zeile geändert wird.
In the below example, the new definition of 'FOO' looks like a two-line change.
$ git diff --stat -w abc.h
...
-#define FOO 7
+#define FOO 105
...
1 files changed, 1 insertions(+), 1 deletions(-)
$
3.) Gültige Kommentarzeilen, die nicht mit dem Muster übereinstimmen (oder) Gültige Quellcodezeilen, die mit dem Muster übereinstimmen, können zu Fehlern bei der Berechnung führen.
Im folgenden Beispiel wird die Zeile „+ blah blah“, die nicht mit „*“ beginnt, nicht als Kommentarzeile erkannt.
+ /*
+ blah blah
+ *
+ */
Im folgenden Beispiel wird die Zeile “+ *ptr” als Kommentarzeile gezählt, da sie mit * beginnt, obwohl es sich um eine gültige Quellcodezeile handelt.
+ printf("n %p",
+ *ptr);
Erik Aronesty
Für die meisten Sprachen müssen Sie, um es richtig zu machen, die ursprüngliche Quelldatei/ast parsen und Kommentare auf diese Weise ausschließen.
Ein Grund dafür ist, dass der Beginn von mehrzeiligen Kommentaren möglicherweise nicht vom Diff abgedeckt wird. Ein weiterer Grund ist, dass das Parsing von Sprachen nicht trivial ist und es oft Dinge gibt, die einen naiven Parser ins Stolpern bringen können.
Ich wollte das für Python machen, aber String-Hacking war gut genug für meine Bedürfnisse.
Für Python können Sie Kommentare ignorieren und versuchen, Dokumentzeichenfolgen zu ignorieren, indem Sie einen benutzerdefinierten Filter verwenden, z. B. diesen:
Eine wilde Vermutung … Hast du es versucht?
git diff --name-status --textconv
? Oder vielleichtgit diff --name-only
?– rodrigo
13. Mai ’13 um 16:55 Uhr
Ja, ich verwende –name-only, aber es gibt (wie gesagt) jede Datei zurück, weil bei jeder Datei die Kommentare geändert wurden. –textconv funktioniert nicht, weil, wie ich auch im Beitrag sagte, git es ignoriert, wenn es kein vollständiges Diff erzeugt.
– Benuvogel
13. Mai 13 um 17:04 Uhr
mögliches Duplikat des Ignorierens von Änderungen, die mit einer Zeichenfolge in git diff übereinstimmen
– richvdh
23. Juni 15 um 14:08 Uhr
@richvdh Ich denke, die Fragen sind ähnlich genug, um als Duplikat betrachtet zu werden, ABER sie haben unterschiedliche richtige Antworten, und diese Frage enthält zusätzliche Antworten, die Vorschläge machen, die das andere Q nicht hat, daher glaube ich, dass es sinnvoll ist, beide zu behalten.
– Benuvogel
23. Juni 15 um 15:23 Uhr
Verwandte: Git 2.30 (Q1 2021) wird vorschlagen
git diff -I<regex>
.– VonC
9. November 20 um 20:16 Uhr