Die Manpage für git-diff
ist ziemlich lang und erklärt viele Fälle, die für einen Anfänger nicht notwendig zu sein scheinen. Zum Beispiel:
git diff origin/master
Die Manpage für git-diff
ist ziemlich lang und erklärt viele Fälle, die für einen Anfänger nicht notwendig zu sein scheinen. Zum Beispiel:
git diff origin/master
Antworten:
Schauen wir uns ein Beispiel für einen erweiterten Unterschied zum Git-Verlauf an (in Commit 1088261f im git.git-Repository ):
diff --git a/builtin-http-fetch.c b/http-fetch.c
similarity index 95%
rename from builtin-http-fetch.c
rename to http-fetch.c
index f3e63d7..e8f44ba 100644
--- a/builtin-http-fetch.c
+++ b/http-fetch.c
@@ -1,8 +1,9 @@
#include "cache.h"
#include "walker.h"
-int cmd_http_fetch(int argc, const char **argv, const char *prefix)
+int main(int argc, const char **argv)
{
+ const char *prefix;
struct walker *walker;
int commits_on_stdin = 0;
int commits;
@@ -18,6 +19,8 @@ int cmd_http_fetch(int argc, const char **argv, const char *prefix)
int get_verbosely = 0;
int get_recover = 0;
+ prefix = setup_git_directory();
+
git_config(git_default_config, NULL);
while (arg < argc && argv[arg][0] == '-') {
Analysieren wir diesen Patch Zeile für Zeile.
Die erste Zeile
diff --git a / builtin-http-fetch.cb / http-fetch.cist ein "git diff" -Header in der Form
diff --git a/file1 b/file2
. Die a/
und b/
Dateinamen sind identisch, es sei denn, es handelt sich um eine Umbenennung / Kopie (wie in unserem Fall). Das --git
soll bedeuten, dass diff im Diff-Format "git" vorliegt.Als nächstes folgen eine oder mehrere erweiterte Kopfzeilen. Die ersten drei
Ähnlichkeitsindex 95% Umbenennen von builtin-http-fetch.c Umbenennen in http-fetch.csagen uns , dass die Datei umbenannt wurde aus
builtin-http-fetch.c
zu , http-fetch.c
und dass diese beiden Dateien sind zu 95% identisch (die verwendet wurde dieses Umbenennungs zu erkennen). Index f3e63d7..e8f44ba 100644Erzählen Sie uns über den Modus einer bestimmten Datei (
100644
bedeutet, dass es sich um eine normale Datei handelt und nicht z. B. über einen Symlink, und dass sie kein ausführbares Berechtigungsbit hat) und über den verkürzten Hash von Preimage (die Version der Datei vor der angegebenen Änderung) und Postimage (die Version der Datei nach Änderung). Diese Zeile wird verwendet, um git am --3way
zu versuchen, eine 3-Wege-Zusammenführung durchzuführen, wenn der Patch nicht selbst angewendet werden kann.Als nächstes folgt ein zweizeiliger einheitlicher Diff-Header
--- a / builtin-http-fetch.c +++ b / http-fetch.cIm Vergleich zum
diff -U
Ergebnis hat es weder eine Änderungszeit von Datei noch eine Änderungszeit von Datei nach Quell- (Preimage) und Zieldateinamen (Postimage). Wenn eine Datei erstellt wurde, ist die Quelle /dev/null
; Wenn die Datei gelöscht wurde, ist das Ziel /dev/null
. diff.mnemonicPrefix
Konfigurationsvariable auf true, anstelle von a/
und b/
Präfixe in diesem zweizeiligen Header können Sie stattdessen c/
, i/
, w/
und o/
als Präfixe, die jeweils zu dem, was Sie vergleichen; siehe git-config (1)Als nächstes kommen ein oder mehrere Unterschiede; Jedes Stück zeigt einen Bereich, in dem sich die Dateien unterscheiden. Unified Format Hunks beginnen mit zeilenartig
@@ -1,8 +1,9 @@oder
@@ -18,6 +19,8 @@ int cmd_http_fetch (int argc, const char ** argv, ...Es ist im Format
@@ from-file-range to-file-range @@ [header]
. Der Dateibereich liegt in der Form vor -<start line>,<number of lines>
und der Dateibereich ist +<start line>,<number of lines>
. Sowohl die Startlinie als auch die Anzahl der Linien beziehen sich auf die Position und Länge des Stücks im Vorbild bzw. im Nachbild. Wenn die Anzahl der Zeilen nicht angezeigt wird, bedeutet dies, dass sie 0 ist.
Der optionale Header zeigt die C-Funktion, bei der jede Änderung auftritt, wenn es sich um eine C-Datei handelt (wie die -p
Option in GNU diff), oder die entsprechende Funktion, falls vorhanden, für andere Dateitypen.
Als nächstes folgt die Beschreibung, wo sich Dateien unterscheiden. Die beiden Dateien gemeinsamen Zeilen beginnen mit einem Leerzeichen. Die Zeilen, die sich zwischen den beiden Dateien tatsächlich unterscheiden, haben eines der folgenden Kennzeichen in der linken Druckspalte:
Also zum Beispiel das erste Stück
#include "cache.h"
#include "walker.h"
-int cmd_http_fetch(int argc, const char **argv, const char *prefix)
+int main(int argc, const char **argv)
{
+ const char *prefix;
struct walker *walker;
int commits_on_stdin = 0;
int commits;
bedeutet, dass cmd_http_fetch
durch ersetzt main
und diese const char *prefix;
Zeile hinzugefügt wurde.
Mit anderen Worten, vor der Änderung sah das entsprechende Fragment der Datei 'builtin-http-fetch.c' folgendermaßen aus:
#include "cache.h"
#include "walker.h"
int cmd_http_fetch(int argc, const char **argv, const char *prefix)
{
struct walker *walker;
int commits_on_stdin = 0;
int commits;
Nach der Änderung sieht dieses Fragment der aktuellen Datei 'http-fetch.c' stattdessen folgendermaßen aus:
#include "cache.h"
#include "walker.h"
int main(int argc, const char **argv)
{
const char *prefix;
struct walker *walker;
int commits_on_stdin = 0;
int commits;
Es könnte geben
\ Kein Zeilenumbruch am DateiendeLinie vorhanden (es ist nicht im Beispiel diff).
Wie Donal Fellows sagte , ist es am besten, das Lesen von Unterschieden an realen Beispielen zu üben, bei denen Sie wissen, was Sie geändert haben.
Verweise:
git blame -C -C
funktioniert es. Es ist eine Entscheidung für das Git-Design. Das Git-Diff-Format zeigt dem Benutzer nur den Ähnlichkeits- (oder Unähnlichkeits-) Index an.
[header]
ist der nächste Vorgänger wie der Beginn der Funktion, der einem Stück vorausgeht. In den meisten Fällen enthält diese Zeile den Namen der Funktion, in der sich der Diff-Block befindet. Dies kann mit diff
gitattribute konfiguriert werden, das auf diff-Treiber und diff-Treiber einschließlich xfuncname
Konfigurationsvariable eingestellt ist.
@@ -1,2 +3,4 @@
Teil des Diff
Ich habe eine Weile gebraucht, um diesen Teil zu verstehen, also habe ich ein minimales Beispiel erstellt.
Das Format ist im Grunde das gleiche wie das diff -u
einheitliche Diff.
Zum Beispiel:
diff -u <(seq 16) <(seq 16 | grep -Ev '^(2|3|14|15)$')
Hier haben wir die Zeilen 2, 3, 14 und 15 entfernt. Ausgabe:
@@ -1,6 +1,4 @@
1
-2
-3
4
5
6
@@ -11,6 +9,4 @@
11
12
13
-14
-15
16
@@ -1,6 +1,4 @@
meint:
-1,6
bedeutet, dass dieses Stück der ersten Datei in Zeile 1 beginnt und insgesamt 6 Zeilen anzeigt. Daher werden die Zeilen 1 bis 6 angezeigt.
1
2
3
4
5
6
-
bedeutet "alt", wie wir es normalerweise als aufrufen diff -u old new
.
+1,4
bedeutet, dass dieses Stück der zweiten Datei in Zeile 1 beginnt und insgesamt 4 Zeilen anzeigt. Daher werden die Zeilen 1 bis 4 angezeigt.
+
bedeutet "neu".
Wir haben nur 4 statt 6 Zeilen, da 2 Zeilen entfernt wurden! Das neue Stück ist nur:
1
4
5
6
@@ -11,6 +9,4 @@
für das zweite Stück ist analog:
In der alten Datei haben wir 6 Zeilen, beginnend in Zeile 11 der alten Datei:
11
12
13
14
15
16
In der neuen Datei haben wir 4 Zeilen, beginnend in Zeile 9 der neuen Datei:
11
12
13
16
Beachten Sie, dass die Zeile 11
die 9. Zeile der neuen Datei ist, da wir bereits 2 Zeilen auf dem vorherigen Hunk entfernt haben: 2 und 3.
Hunk-Header
Je nach Ihrer git - Version und Konfiguration können Sie auch eine Codezeile neben der bekommen @@
Linie, zum Beispiel des func1() {
in:
@@ -4,7 +4,6 @@ func1() {
Dies kann auch mit der -p
Flagge der Ebene erhalten werden diff
.
Beispiel: alte Datei:
func1() {
1;
2;
3;
4;
5;
6;
7;
8;
9;
}
Wenn wir die Linie entfernen 6
, zeigt der Unterschied :
@@ -4,7 +4,6 @@ func1() {
3;
4;
5;
- 6;
7;
8;
9;
Beachten Sie, dass dies nicht die richtige Zeile ist für func1
: Es wurden Zeilen 1
und übersprungen 2
.
Diese großartige Funktion sagt oft genau, zu welcher Funktion oder Klasse jeder Hunk gehört, was sehr nützlich ist, um den Unterschied zu interpretieren.
Wie der Algorithmus zur Auswahl des Headers genau funktioniert, wird unter folgender Adresse erläutert: Woher kommt der Auszug im Git-Diff-Hunk-Header?
@@ -1,6 +1,4 @@
pls lesen Sie nicht -1
als minus one
oder +1
als plus one
stattdessen lesen Sie dies wie line 1 to 6
in der alten (ersten) Datei. Beachten Sie hier - implies "old"
nicht minus. Übrigens, danke für die Klarstellung ... haash.
+1,4
sagt, dass dieses Stück den Zeilen 1 bis 4 der zweiten Datei entspricht ". Dies liegt daran, dass +1,4
möglicherweise nicht kontingente Kontextzeilen verwendet werden. Vielmehr +1,4
bedeutet " " tatsächlich, dass " in dieser 'Version' der Datei Zeilen (dh Kontextzeilen) vorhanden sind4
". Es ist wichtig , die Bedeutung der zu verstehen +
, -
und <whitespace>
zu Beginn dieser Zeilen, wie es um die Auslegung von hunks gilt. Ein visuelleres Beispiel: youtube.com/watch?v=1tqMjJeyKpw
Hier ist das einfache Beispiel.
diff --git a/file b/file
index 10ff2df..84d4fa2 100644
--- a/file
+++ b/file
@@ -1,5 +1,5 @@
line1
line2
-this line will be deleted
line4
line5
+this line is added
Hier ist eine Erklärung (siehe Details hier ).
--git
ist kein Befehl, das heißt, es ist eine Git-Version von Diff (nicht Unix)a/ b/
sind Verzeichnisse, sie sind nicht real. Es ist nur eine Annehmlichkeit, wenn wir mit derselben Datei arbeiten (in meinem Fall befindet sich a / im Index und b / im Arbeitsverzeichnis).10ff2df..84d4fa2
sind Blob-IDs dieser 2 Dateien100644
ist das "Modusbit", das angibt, dass dies eine reguläre Datei ist (nicht ausführbar und keine symbolische Verknüpfung).--- a/file +++ b/file
Minuszeichen zeigen Linien in der a / Version, fehlen aber in der b / Version; und Pluszeichen zeigen Zeilen an, die in a / fehlen, aber in b / vorhanden sind (in meinem Fall bedeutet --- gelöschte Zeilen und +++ bedeutet hinzugefügte Zeilen in b / und dies ist die Datei im Arbeitsverzeichnis).@@ -1,5 +1,5 @@
Um dies zu verstehen, ist es besser, mit einer großen Datei zu arbeiten. Wenn Sie zwei Änderungen an verschiedenen Stellen haben, erhalten Sie zwei Einträge wie @@ -1,5 +1,5 @@
; Angenommen, Sie haben die Datei line1 ... line100 und haben line10 gelöscht und fügen neue line100 hinzu - Sie erhalten:@@ -7,7 +7,6 @@ line6 line7 line8 line9 -this line10 to be deleted line11 line12 line13 @@ -98,3 +97,4 @@ line97 line98 line99 line100 +this is new line100
644
) sind oktal zu lesen (Werte: 1, 2, 4 bzw. eXecute-, Write- und Read-Berechtigung) und entsprechen in dieser Reihenfolge den Berechtigungen Eigentümer (Benutzer), dann Gruppe und dann Andere. Kurz gesagt 644
würde dies bedeuten, wenn es symbolisch geschrieben wird u=rw,og=r
, dass es für alle lesbar ist, aber nur vom Eigentümer geschrieben werden kann. Die anderen Ziffern auf der linken Seite codieren andere Informationen, z. B. wenn es sich um einen Symlink usw. handelt. Die Werte sind unter github.com/git/git/blob/… zu sehen . Die erste 1 an dieser Position ist "reguläre Datei".
Das Standardausgabeformat (das ursprünglich von einem Programm stammt, das bekannt ist, als diff
ob Sie nach weiteren Informationen suchen möchten) wird als "Unified Diff" bezeichnet. Es enthält im Wesentlichen 4 verschiedene Arten von Linien:
+
,-
, undIch rate Ihnen, das Lesen von Unterschieden zwischen zwei Versionen einer Datei zu üben, in denen Sie genau wissen, was Sie geändert haben. So erkennen Sie genau, was los ist, wenn Sie es sehen.
Auf meinem Mac:
info diff
Wählen Sie dann: Output formats
-> Context
-> Unified format
-> Detailed Unified
:
Oder online man diff on gnu auf dem gleichen Weg zum gleichen Abschnitt:
Datei: diff.info, Knoten: Detailliertes Unified, Weiter: Beispiel Unified, Up: Unified Format
Detaillierte Beschreibung des einheitlichen Formats ......................................
Das einheitliche Ausgabeformat beginnt mit einem zweizeiligen Header, der folgendermaßen aussieht:
--- FROM-FILE FROM-FILE-MODIFICATION-TIME +++ TO-FILE TO-FILE-MODIFICATION-TIME
Der Zeitstempel sieht aus wie "2002-02-21 23: 30: 39.942229878 -0800", um Datum, Uhrzeit in Sekundenbruchteilen und Zeitzone anzugeben.
Sie können den Inhalt des Headers mit der Option "--label = LABEL" ändern. siehe * Hinweis Alternative Namen ::.
Als nächstes kommen ein oder mehrere Unterschiede; Jedes Stück zeigt einen Bereich, in dem sich die Dateien unterscheiden. Unified Format Hunks sehen folgendermaßen aus:
@@ FROM-FILE-RANGE TO-FILE-RANGE @@ LINE-FROM-EITHER-FILE LINE-FROM-EITHER-FILE...
Die beiden Dateien gemeinsamen Zeilen beginnen mit einem Leerzeichen. Die Zeilen, die sich zwischen den beiden Dateien tatsächlich unterscheiden, haben eines der folgenden Kennzeichen in der linken Druckspalte:
`+ 'Hier wurde der ersten Datei eine Zeile hinzugefügt.
`- 'Hier wurde eine Zeile aus der ersten Datei entfernt.
Aus Ihrer Frage geht nicht hervor, welchen Teil der Unterschiede Sie verwirren: den tatsächlichen Unterschied oder die zusätzlichen Header-Informationen, die Git druckt. Nur für den Fall, hier ist eine kurze Übersicht über den Header.
Die erste Zeile ist so etwas wie diff --git a/path/to/file b/path/to/file
- offensichtlich sagt sie Ihnen nur, für welche Datei dieser Abschnitt des Diff bestimmt ist. Wenn Sie die boolesche Konfigurationsvariable festlegen diff.mnemonic prefix
, wird das a
und b
in aussagekräftigere Buchstaben wie c
und w
(Festschreibungs- und Arbeitsbaum) geändert .
Als nächstes gibt es "Moduszeilen" - Zeilen, in denen Sie alle Änderungen beschreiben, bei denen der Inhalt der Datei nicht geändert wird. Dies umfasst neue / gelöschte Dateien, umbenannte / kopierte Dateien und Berechtigungsänderungen.
Schließlich gibt es eine Linie wie index 789bd4..0afb621 100644
. Sie werden sich wahrscheinlich nie darum kümmern, aber diese 6-stelligen Hex-Zahlen sind die abgekürzten SHA1-Hashes der alten und neuen Blobs für diese Datei (ein Blob ist ein Git-Objekt, das Rohdaten wie den Inhalt einer Datei speichert). Und natürlich 100644
ist dies der Dateimodus - die letzten drei Ziffern sind offensichtlich Berechtigungen. Die ersten drei geben zusätzliche Informationen zu Dateimetadaten ( SO-Post, die dies beschreibt ).
Danach können Sie mit der einheitlichen Standard-Diff-Ausgabe fortfahren (genau wie beim Klassiker diff -U
). Es ist in Hunks aufgeteilt - ein Hunk ist ein Abschnitt der Datei, der Änderungen und deren Kontext enthält. Vor jedem Hunk stehen zwei Zeilen ---
und +++
Zeilen, die die betreffende Datei bezeichnen. Der tatsächliche Unterschied besteht (standardmäßig) aus drei Kontextzeilen auf beiden Seiten der -
und +
-Zeilen, in denen die entfernten / hinzugefügten Zeilen angezeigt werden.
index
Zeile. Bestätigt mitgit hash-object ./file