Wie kann man ein Commit mit seinem Elternteil unterscheiden?

460

Gibt es neben dem Schreiben eines Alias ​​oder Skripts einen kürzeren Befehl zum Abrufen des Diff für ein bestimmtes Commit?

git diff 15dc8^..15dc8

Wenn Sie nur die einzelne git diff 15dc8Festschreibungs- ID angeben, unterscheidet sich diese Festschreibung für HEAD.

Brian L.
quelle
Das Coolste daran wäre, dass dies mit "git difftool" funktioniert und die Werkzeuge verwendet, um den Unterschied zu zeigen.
Orip
Als Referenz zeigt die Antwort auf diese andere Frage, wie Sie einen Bash- basierten
Nick

Antworten:

641

Verwenden Sie git show $COMMIT. Es zeigt Ihnen die Protokollnachricht für das Commit und den Unterschied zu diesem bestimmten Commit.

Mipadi
quelle
45
Schade, dass es kein Difftool verwenden kann :(
Orip
1
@orip Sie können GIT_EXTERNAL_DIFF immer auf ein Skript setzen, das dasselbe tut wie Ihr Difftool.
Slacy
7
Ich bevorzuge die Antwort von JakubNarebski, da der dort angegebene Commit-Ausdruck in vielen Zusammenhängen funktioniert
RichVel
1
Wenn kein Unterschied angezeigt wird, gibt es wahrscheinlich keine tatsächlichen Änderungen, wie bei einem Zusammenführungs-Commit
Devin G Rhode
6
@PTWithy: Die Frage lautete: "Gibt es einen kürzeren Befehl zum Abrufen des Diff für ein bestimmtes Commit?", Den diese Frage beantwortet.
Mipadi
439

Verwenden:

git diff 15dc8^!

wie im folgenden Fragment der Manpage git-rev-parse (1) (oder in der modernen Manpage gitrevisions (7) ) beschrieben:

Es gibt zwei weitere Abkürzungen zum Benennen einer Menge, die aus einem Commit und seinen übergeordneten Commits besteht. Die Notation r1 ^ @ bedeutet alle Eltern von r1. r1 ^! Beinhaltet Commit r1, schließt jedoch alle Eltern aus.

Dies bedeutet, dass Sie 15dc8^!als Abkürzung für 15dc8^..15dc8jeden Ort in Git verwenden können, an dem Überarbeitungen erforderlich sind. Für den Befehl diffgit diff 15dc8^..15dc8 wird verstanden als git diff 15dc8^ 15dc8, was den Unterschied zwischen dem übergeordneten Element von commit ( 15dc8^) und commit ( 15dc8) bedeutet.

Hinweis : In der Beschreibung in git-rev-parse(1)manpage spricht über Revisionsbereichen , wo es auch Commits für merge arbeiten muss, mit mehr als einem Elternteil. Dann r1^!ist " r1 --not r1^@" dh " r1 ^r1^1 ^r1^2 ..."


Sie können auch verwenden git show COMMIT, um eine Commit-Beschreibung und ein Diff für ein Commit abzurufen. Wenn Sie nur diff wollen, können Sie verwendengit diff-tree -p COMMIT

Jakub Narębski
quelle
7
Dies sollte die akzeptierte Antwort sein, es ist viel ordentlicher. Der letzte Satz des git-rev-parse-Extrakts ist jedoch ziemlich verwirrend - er scheint "Bereich vom Elternteil dieses Commits bis zu diesem Commit" zu bedeuten.
RichVel
1
@RichVel: Es ist etwas verwirrend, weil es versucht, auch die Situation zu beschreiben, in der Commit mehr als ein übergeordnetes Element hat (ist ein Merge-Commit). r1 ^! funktioniert auch dann wie erwartet.
Jakub Narębski
@ JakubNarębski: Guter Punkt, vielleicht könnten Sie Ihre Antwort bearbeiten, um Ihr Verständnis der Fälle von einem Elternteil und mehreren Elternteilen zusammenzufassen - separate Aussagen zu jedem Fall könnten einfacher zu verstehen sein.
RichVel
1
@ JakubNarębski: ja viel besser! Ich benutze diese Verknüpfung jetzt die ganze Zeit - danke.
RichVel
1
Die ^!übergeordnete Kurzschreibweise funktioniert bei verschiedenen Commits ordnungsgemäß mit difftool, bei Zusammenführungs-Commits ist der Unterschied jedoch umgekehrt. Warum so?
HPPy
56

Wenn Sie wissen, wie weit zurück, können Sie etwas versuchen wie:

# Current branch vs. parent
git diff HEAD^ HEAD

# Current branch, diff between commits 2 and 3 times back
git diff HEAD~3 HEAD~2

Vorherige Commits funktionieren ungefähr so:

# Parent of HEAD
git show HEAD^1

# Grandparent
git show HEAD^2

Es gibt viele Möglichkeiten, wie Sie Commits festlegen können:

# Great grandparent
git show HEAD~3

Siehe diese Seite für Details .

Paul Vincent Craven
quelle
2
HEAD ^ 2 ist nicht der Großelternteil, wenn HEAD ^ 1 Papa ist, dann ist HEAD ^ 2 Mama. Verwenden Sie HEAD ~ 2 für Papas Papa.
Binarian
11

Wie @mipadi hervorhebt, können Sie verwenden git show $COMMIT, aber dies zeigt auch einige Header und die Commit-Nachricht. Wenn Sie ein gerades Diff möchten, verwenden Sie git show --pretty=format:%b $COMMIT.

Dies ist offensichtlich keine sehr kurze Hand, daher behalte ich diesen Alias ​​in meiner .gitconfig

    [alias]
      sd = show --pretty=format:%b

Dies ermöglicht es mir, diffgit sd $COMMIT zu zeigen .

Øystein Steimler
quelle
1
Dieser Alias ​​kann --color enthalten, was das Lesen erleichtert: sd = show --color --pretty = Format:% b
RichVel
@ RichVel In der Tat! Sehr guter Punkt. Wenn Sie in git standardmäßig Farben aktiviert haben, benötigen Sie diesen Schalter jedoch nicht. Das mache ich normalerweise.
Øystein Steimler
5

Viele der genannten Beispiele (z. B. git diff 15dc8^!oder git diff 15dc8^..15dc8) funktionieren nicht, wenn Sie zsh verwenden und die extendedglobOption festgelegt haben. Sie können das Problem auf eine der folgenden drei Arten beheben:

  1. unsetopt extendedglob (und / oder entfernen Sie es aus .zshrc)

  2. setopt NO_NOMATCH (und / oder in .zshrc setzen)

  3. Entkomme dem Caret und knalle jedes Mal mit einem Backslash, z git diff 15dc8\^\!

Ville
quelle
3
git diff 15dc8 15dce~1

~ 1 bedeutet 'Eltern', ~ 2 'Großeltern usw.

John Lawrence Aspden
quelle
2

Die obige Lösung von Paul hat das getan, was ich mir erhofft hatte.

$ git diff HEAD^1

Es ist auch nützlich, Aliase wie die erwähnten Kochfelder hinzuzufügen. Wenn Sie Folgendes in den Abschnitt [Alias] Ihrer ~ / .gitconfig-Datei einfügen, können Sie mit der Kurzschrift den Unterschied zwischen Kopf und Vorgänger anzeigen.

[alias]
    diff-last = diff HEAD^1

Wenn Sie dann $ git diff-last ausführen, erhalten Sie Ihr Ergebnis. Beachten Sie, dass dies auch beinhalten alle Änderungen , die Sie haben noch nicht so gut wie die diff zwischen Commits verpflichtet. Wenn Sie Änderungen ignorieren möchten, die Sie noch nicht festgeschrieben haben, können Sie diff verwenden, um den HEAD direkt mit dem übergeordneten Element zu vergleichen:

$ git diff HEAD^1 HEAD
Graham R. Armstrong
quelle
0

Verwendet Aliase, beantwortet Ihre Frage also nicht genau, aber ich finde diese nützlich, um das zu tun, was Sie beabsichtigen ...

alias gitdiff-1="git log --reverse|grep commit|cut -d ' ' -f2|tail -n 2|head -n 2|xargs echo|sed -e 's/\s/../'|xargs -n 1 git diff"
alias gitdiff-2="git log --reverse|grep commit|cut -d ' ' -f2|tail -n 3|head -n 2|xargs echo|sed -e 's/\s/../'|xargs -n 1 git diff"
alias gitdiff-3="git log --reverse|grep commit|cut -d ' ' -f2|tail -n 4|head -n 2|xargs echo|sed -e 's/\s/../'|xargs -n 1 git diff"

alias gitlog-1="git log --reverse|grep commit|cut -d ' ' -f2|tail -n 2|head -n 2|xargs echo|sed -e 's/\s/../'|xargs -n 1 git log --summary"
alias gitlog-2="git log --reverse|grep commit|cut -d ' ' -f2|tail -n 3|head -n 2|xargs echo|sed -e 's/\s/../'|xargs -n 1 git log --summary"
alias gitlog-3="git log --reverse|grep commit|cut -d ' ' -f2|tail -n 4|head -n 2|xargs echo|sed -e 's/\s/../'|xargs -n 1 git log --summary"
Kochfelder
quelle