Wie unterscheide ich dieselbe Datei zwischen zwei verschiedenen Commits in demselben Zweig?

1144

Wie kann ich in Git dieselbe Datei zwischen zwei verschiedenen Commits (nicht zusammenhängend) in demselben Zweig (z. B. Master) vergleichen?

Ich suche nach einer Vergleichsfunktion wie der in Visual SourceSafe (VSS) oder Team Foundation Server (TFS).
Ist es in Git möglich?

systempuntoout
quelle

Antworten:

1476

Aus der git-diffManpage:

git diff [--options] <commit> <commit> [--] [<path>...]

Um beispielsweise den Unterschied für eine Datei "main.c" zwischen jetzt und zwei Commits zurück zu sehen, sind hier drei äquivalente Befehle aufgeführt:

$ git diff HEAD^^ HEAD main.c
$ git diff HEAD^^..HEAD -- main.c
$ git diff HEAD~2 HEAD -- main.c
Mipadi
quelle
43
Das ..ist nicht wirklich notwendig, obwohl es damit funktioniert (außer vielleicht in ziemlich alten Versionen). Sie können auch SHA1s verwenden git logoder gitkfinden, wenn die beiden Commits sehr weit voneinander entfernt sind. gitkhat auch ein "diff selected -> this" und "diff this -> selected" in seinem Kontextmenü.
Cascabel
17
Funktioniert dies auch dann, wenn der Dateiname zwischen den beiden Commits geändert wurde?
Rubenjohn
26
Also, was ist der Zweck des "-"
user64141
29
@ user64141 Das --ist nützlich, zB wenn Sie eine Datei mit dem Namen haben -p. Gut in Skripten zu verwenden, nur in seltenen Fällen in der Praxis erforderlich.
Palec
13
Hinweis: Sie müssen Pfade relativ zum Stammverzeichnis des Repos verwenden. Pfade relativ zum aktuellen Arbeitsverzeichnis funktionieren nicht.
Kevin Wheeler
281

Sie können auch zwei verschiedene Dateien in zwei verschiedenen Revisionen vergleichen:

git diff <revision_1>:<file_1> <revision_2>:<file_2>

Jakub Narębski
quelle
25
Beachten Sie, dass es so aussieht, als ob <file_1>und <file_2>im aktuellen Verzeichnis, nicht im git-verwalteten Verzeichnis der obersten Ebene, ./Unix vorangestellt werden muss :<revision_1>:./filename_1
Andre Holzner
7
<Revision>: Kann nicht festgeschrieben werden, sodass Sie sich von einer Datei unterscheiden können, die noch nicht festgeschrieben wurde.
Jaroslaw Nikitenko
2
Beachten Sie, dass unter Windows '/' für Dateipfade verwendet werden muss, nicht '\'.
np8
88

Wenn Sie das "Difftool" konfiguriert haben, können Sie es verwenden

git difftool revision_1:file_1 revision_2:file_2

Beispiel: Vergleichen einer Datei von ihrem letzten Commit mit ihrem vorherigen Commit in demselben Zweig: Angenommen, Sie befinden sich in Ihrem Projektstammordner

$git difftool HEAD:src/main/java/com.xyz.test/MyApp.java HEAD^:src/main/java/com.xyz.test/MyApp.java

Sie sollten die folgenden Einträge in Ihrer ~ / .gitconfig- oder in der project / .git / config-Datei haben. Installieren Sie das p4merge [Dies ist mein bevorzugtes Diff- und Merge-Tool]

[merge]
    tool = p4merge
    keepBackup = false
[diff]
    tool = p4merge
    keepBackup = false
[difftool "p4merge"]
    path = C:/Program Files (x86)/Perforce/p4merge.exe
[mergetool]
    keepBackup = false
[difftool]
    keepBackup = false
[mergetool "p4merge"]
    path = C:/Program Files (x86)/Perforce/p4merge.exe
    cmd = p4merge.exe \"$BASE\" \"$LOCAL\" \"$REMOTE\" \"$MERGED\"
Anver Sadhat
quelle
50

Überprüfen Sie $ git log, kopieren Sie die SHA-1- ID der beiden verschiedenen Commits und führen Sie den git diffBefehl mit diesen IDs aus. zum Beispiel:

$ git diff (sha-id-one) (sha-id-two)
Vibhuti
quelle
18
Wenn Sie das Diff für eine bestimmte Datei möchten, fügen Sie den Pfad am Ende des Befehls hinzu.
hBrent
Führen Sie auch einen "Git-Pull" durch, um die vollständigen Bauminformationen herunterzuladen, wenn sich die beiden Commits über verschiedene Zweige erstrecken. Andernfalls wird der Fehler "fatal: bad object" angezeigt.
user238607
4
git diff (sha-id-one) (sha-id-two) -- filename.ext Ohne den Dateinamen werden die Unterschiede aller Dateien in diesen beiden Commits aufgelistet .
SherylHohman
40

Wenn Sie alle Änderungen an der Datei zwischen den beiden Commits auf Commit-by-Commit-Basis anzeigen möchten, können Sie dies auch tun

git log -u $start_commit..$end_commit -- path/to/file

cxreg
quelle
Was ist "$ start_commit" und "$ end_commit"? Sind sie wörtlich oder können Sie ein Beispiel geben, wenn nicht?
Peter Mortensen
Dies sind Shell-Variablen, die die Start- und Endrevision enthalten, die stattdessen sha1-Literale oder refs sein können
cxreg
21

Hier ist ein Perl-Skript, das Git diff-Befehle für eine bestimmte Datei ausgibt, wie sie in einem Git-Protokollbefehl enthalten sind.

Z.B

git log pom.xml | perl gldiff.pl 3 pom.xml

Ausbeuten:

git diff 5cc287:pom.xml e8e420:pom.xml
git diff 3aa914:pom.xml 7476e1:pom.xml
git diff 422bfd:pom.xml f92ad8:pom.xml

Diese können dann ausgeschnitten und in eine Shell-Fenstersitzung eingefügt oder an weitergeleitet werden /bin/sh.

Anmerkungen:

  1. Die Zahl (in diesem Fall 3) gibt an, wie viele Zeilen gedruckt werden sollen
  2. Die Datei (in diesem Fall pom.xml) muss an beiden Stellen übereinstimmen (Sie können sie in eine Shell-Funktion einschließen, um an beiden Stellen dieselbe Datei bereitzustellen) oder als Shell-Skript in ein Binärverzeichnis stellen

Code:

# gldiff.pl
use strict;

my $max  = shift;
my $file = shift;

die "not a number" unless $max =~ m/\d+/;
die "not a file"   unless -f $file;

my $count;
my @lines;

while (<>) {
    chomp;
    next unless s/^commit\s+(.*)//;
    my $commit = $1;
    push @lines, sprintf "%s:%s", substr($commit,0,6),$file;
    if (@lines == 2) {
        printf "git diff %s %s\n", @lines;
        @lines = ();
    }
    last if ++$count >= $max *2;
}
user2520657
quelle
14

Wenn Sie einen Diff mit mehr als einer Datei erstellen möchten, verwenden Sie die von @mipadi angegebene Methode:

ZB unterscheiden sich zwischen HEADund Ihren master, um alle .coffeeDateien zu finden :

git diff master..HEAD -- `find your_search_folder/ -name '*.coffee'`

Dadurch werden Sie rekursiv nach your_search_folder/allen .coffeeDateien durchsucht und zwischen ihnen und ihren masterVersionen unterschieden.

Andrei-Niculae Petre
quelle
13

Wenn Sie mehrere Dateien oder Verzeichnisse haben und nicht fortlaufende Commits vergleichen möchten, können Sie dies tun:

Erstellen Sie eine temporäre Verzweigung ( "Revision" in diesem Beispiel)

git checkout -b revision

Zurück zum ersten Festschreibungsziel

git reset --hard <commit_target>

Kirschernte bei Interessenten

git cherry-pick <commit_interested> ...

Diff anwenden

git diff <commit-target>^

Wenn du fertig bist

git branch -D revision
dvdvck
quelle
2
Danke für diese Lösung. Für meinen Anwendungsfall hat es gut funktioniert. Das einzige, was ich aktualisieren würde, ist, dass Sie den Zweig erst löschen können, wenn Sie fertig sind.
Steven Dix
9

Nur eine andere Möglichkeit, Gits Großartigkeit zu nutzen ...

git difftool HEAD HEAD@{N} /PATH/FILE.ext
Eddie B.
quelle
Ich habe einen Alias ​​aus dieser Antwort definiert, der mit Bash funktioniert:difftool-file = "!git difftool HEAD@{\"$2\"} HEAD \"$1\" #"
Blueogive
2

Wenn Sie einen einfachen visuellen Vergleich unter Windows wünschen, wie Sie ihn in Visual SourceSafe oder Team Foundation Server (TFS) erhalten können, versuchen Sie Folgendes:

  • Klicken Sie im Datei-Explorer mit der rechten Maustaste auf die Datei
  • wähle 'Git History'

Hinweis: Nach dem Upgrade auf Windows 10 habe ich die Git-Kontextmenüoptionen verloren. Sie können jedoch dasselbe mit 'gitk' oder 'gitk filename' in einem Befehlsfenster erreichen.

Sobald Sie 'Git History' aufrufen, wird das Git GUI-Tool mit einem Verlauf der Datei im oberen linken Bereich gestartet. Wählen Sie eine der Versionen aus, die Sie vergleichen möchten. Klicken Sie dann mit der rechten Maustaste auf die zweite Version und wählen Sie eine der beiden

Diff this -> ausgewählt

oder

Diff ausgewählt -> dies

Farbcodierte Unterschiede werden im unteren linken Bereich angezeigt.

Ressource
quelle
Hinweis für Downvoter: Dies ist eine einfache Lösung, die einfach zu implementieren ist und das Problem des OP behebt. Es funktioniert unter Windows, das das OP eindeutig verwendet (siehe Verweise auf TFS und VSS in der Frage).
Ressource