Git Schuld - vorherige Commits?

391

Ist es möglich zu sehen, wer eine bestimmte Zeile vor dem Commit bearbeitet hat git blame, wie von einem Commit-Verlauf für eine bestimmte Zeile?

Zum Beispiel führe ich Folgendes aus (für das hervorragende uncrustifyProjekt):

$ git blame -L10,+1 src/options.cpp
^fe25b6d (Ben Gardner 2009-10-17 13:13:55 -0500 10) #include "prototypes.h"

Wie kann ich herausfinden, wer diese Zeile vor dem Festschreiben bearbeitet hat fe25b6d? Und wer hat es vor diesem Commit bearbeitet ?

Beruhige Alien
quelle
7
Wenn der Grund, warum Sie nach vorherigen Commits suchen, Leerzeichenänderungen sind, verwenden Sie die -wOption. Es gibt auch -Mfür verschobenen / kopierten Code
brita_
Um nach allen Commits zu suchen, die ein bestimmtes Wort beinhalten, siehe mein Skript unten
VonC
Hier ist ein nützliches Skript, um diese Funktionalität auf github greasyfork.org/en/scripts/… hinzuzufügen
Aaron Hoffman
3
Ich bin mir nicht sicher, wie Github aussah, als @AaronHoffman gepostet hat, aber es ist jetzt sehr einfach, Github die Schuld zu geben - und Schuld für frühere Versionen zu bekommen .
Ruffin

Antworten:

389
git blame -L 10,+1 fe25b6d^ -- src/options.cpp

Sie können eine Revision angeben, bei der Git-Schuld zurückblicken soll (anstelle der Standardeinstellung von HEAD). fe25b6d^ist der Elternteil von fe25b6d.

Bernstein
quelle
107
Können Sie einen vollständigen Verlauf abrufen, ohne den Befehl mehrmals mit verschiedenen Hashes erneut eingeben zu müssen?
Anders Zommarin
13
Ich glaube nicht, dass Git eine eingebaute Methode hat, um jede Schuld zu bekommen, die eine Zeilennummer berührt hat (was sinnvoll ist, da eine bestimmte Zeile aufgrund von Einfügungen und Löschungen im gesamten Verlauf einer Datei möglicherweise keine konsistente Zeilennummer hat von Linien).
Amber
17
@Amber: Ich bin mir ziemlich sicher, dass Sie Recht haben, dass die Funktion nicht existiert, aber es scheint, als könnte sie naiv implementiert werden, indem Sie einfach das tun, was ein Mensch tun würde: einmal beschuldigen, die gemeldeten Informationen abrufen, beschuldigen , und so weiter.
Cascabel
15
git gui macht es ziemlich einfach, den Verlauf einer Zeile zu überprüfen, da die Versionen anklickbar sind.
Zitrax
5
@shadyabhi --wird häufig als Trennzeichen in Befehlszeilenargumenten verwendet. Im Fall von Git wird es normalerweise verwendet, um Dinge wie Commit-Hashes von einer Liste von Dateinamen zu trennen.
Amber
191

Mit git log -L können Sie die Entwicklung eines Zeilenbereichs anzeigen.

Beispielsweise :

git log -L 15,23:filename.txt

bedeutet "Verfolgen Sie die Entwicklung der Zeilen 15 bis 23 in der Datei mit dem Namen filename.txt".

Navneet
quelle
12
Dies ist eine solide Antwort und befasst sich mit der obigen Frage von Anders Zommarin, wie die Änderungen an bestimmten Zeilen im Laufe der Zeit angezeigt werden können.
Bigtex777
4
Zu Ihrer Information : Git-Protokoll -L <Start>, <Ende>: <Datei> erfordert Git 1.8.4+. Siehe: git-scm.com/docs/git-log#git-log--Lltstartgtltendgtltfilegt für Syntaxoptionen
Neon
30

Bernsteins Antwort ist richtig, aber ich fand sie unklar; Die Syntax lautet:

git blame {commit_id} -- {path/to/file}

Hinweis: Mit --wird das baumartige sha1 von den relativen Dateipfaden getrennt. 1

Zum Beispiel:

git blame master -- index.html

Volle Anerkennung an Amber für das Wissen über alle Dinge! :) :)

ThorSummoner
quelle
1
Ich stimme Ihrem Gefühl zu. Das Kommentarsystem ist jedoch zu eingeschränkt, um alle Informationen klar darzustellen. Ich habe den Inhalt dieser Antwort in einem Kommentar hinzugefügt. Ich bestehe jedoch darauf, diese Antwort zu hinterlassen, um den Zugang zu erleichtern.
ThorSummoner
1
Es sollte entweder ein separater Beitrag oder eine Bearbeitung sein. Ich mag es als separate Antwort.
Flimm
27

Vielleicht möchten Sie Folgendes überprüfen:

git gui blame <filename>

Bietet Ihnen eine schöne grafische Darstellung von Änderungen wie "Git-Schuld", aber mit anklickbaren Links pro Zeile, um zu früheren Commits überzugehen. Bewegen Sie den Mauszeiger über die Links, um ein Popup mit Festschreibungsdetails zu erhalten. Nicht meine Credits ... habe es hier gefunden:

http://zsoltfabok.com/blog/2012/02/git-blame-line-history/

git guiist eine grafische Tcl / Tc-Schnittstelle zu Git. Ohne weitere Parameter wird eine ziemlich einfache, aber nützliche grafische App zum Festschreiben von Dateien, Hunks oder sogar einzelnen Zeilen und ähnlichen Befehlen wie Ändern, Zurücksetzen, Drücken ... gestartet. Sie ist Teil der Git Stock Suite. Unter Windows ist es im Installationsprogramm enthalten. Auf debian - ich weiß nichts über andere * nix-Systeme - muss es separat installiert werden:

apt-get install git-gui

Aus den Dokumenten:

https://git-scm.com/docs/git-gui

BESCHREIBUNG

Eine Tcl / Tk-basierte grafische Benutzeroberfläche für Git. git gui konzentriert sich darauf, Benutzern das Vornehmen von Änderungen an ihrem Repository zu ermöglichen, indem neue Commits vorgenommen, vorhandene geändert, Zweige erstellt, lokale Zusammenführungen durchgeführt und Remote-Repositorys abgerufen / verschoben werden.

Im Gegensatz zu gitk konzentriert sich git gui auf die Commit-Generierung und die Annotation einzelner Dateien und zeigt keinen Projektverlauf an. Es werden jedoch Menüaktionen bereitgestellt, um eine Gitk-Sitzung innerhalb der Git-GUI zu starten.

git gui funktioniert bekanntermaßen auf allen gängigen UNIX-Systemen, Mac OS X und Windows (sowohl unter Cygwin als auch unter MSYS). Soweit möglich werden die betriebssystemspezifischen Richtlinien für Benutzeroberflächen befolgt, wodurch git gui eine ziemlich native Benutzeroberfläche für Benutzer ist.

BEFEHLE

Schuld

Starten Sie einen Schuld-Viewer für die angegebene Datei in der angegebenen Version (oder ein Arbeitsverzeichnis, falls nicht angegeben).

Browser

Starten Sie einen Baumbrowser, der alle Dateien im angegebenen Commit anzeigt. Über den Browser ausgewählte Dateien werden im Schuldbetrachter geöffnet.

Citool

Starten Sie git gui und vereinbaren Sie genau ein Commit, bevor Sie die Shell verlassen und zur Shell zurückkehren. Die Benutzeroberfläche kann nur Aktionen festschreiben, wodurch die Startzeit der Anwendung geringfügig verkürzt und die Menüleiste vereinfacht wird.

Ausführung

Zeigen Sie die aktuell ausgeführte Version von git gui an.

Holger Böhnke
quelle
Es funktioniert nicht bei mir. Ich kann auf die Änderung in der angegebenen Zeile klicken, aber dadurch wird nur die Ansicht für dieses Commit geändert, und die aktuelle Zeile wird jetzt wie folgt angezeigt this: Aber wie sehe ich die vorherige Version der Zeile und wann wurde sie hinzugefügt?
BeeOnRope
Dies ist der einzige Anwendungsfall, von dem ich weiß, wo Git Gui die beste Lösung ist
kambunctious
17

Aufbauend auf der vorherigen Antwort sollte dieser Bash-Einzeiler Ihnen das geben, wonach Sie suchen. Es zeigt den Git-Schuldverlauf für eine bestimmte Zeile einer bestimmten Datei in den letzten 5 Revisionen an:

LINE=10 FILE=src/options.cpp REVS=5; for commit in $(git rev-list -n $REVS HEAD $FILE); do git blame -n -L$LINE,+1 $commit -- $FILE; done

In der Ausgabe dieses Befehls wird möglicherweise der Inhalt der Zeilenänderung oder die angezeigte Zeilennummer für ein bestimmtes Commit geändert.

Dies weist häufig darauf hin, dass die Zeile nach diesem bestimmten Commit zum ersten Mal hinzugefügt wurde. Es könnte auch anzeigen, dass die Zeile aus einem anderen Teil der Datei verschoben wurde.

Will Sheppard
quelle
5
Beachten Sie, dass dies die letzten $ REVS-Revisionen sind, in denen sich $ FILE geändert hat, und nicht die letzten $ REVS-Revisionen, in denen sich $ LINE geändert hat.
Max Nanasy
Auf welche Antwort beziehen Sie sich?
Flimm
Ich erinnere mich nicht mehr. Möglicherweise hätte ich meine Antwort besser zukunftssicher machen können.
Will Sheppard
12

Es gibt auch recursive-blame. Es kann mit installiert werden

npm install -g recursive-blame
Thomas W.
quelle
11

Eine sehr einzigartige Lösung für dieses Problem ist die Verwendung von Git Log:

git log -p -M --follow --stat - Pfad / zu / Ihrer / Datei

Wie von Andre hier erklärt

Mannu
quelle
1
Ich habe einen Alias ​​erstellt, um dies zu verwenden: git config --global alias.changes 'log -p -M --follow --stat --'und dann kann ich einfach git changes path/to/your/file
eingeben
Dies ist bei weitem die beste Antwort und genau das, wonach ich gesucht habe. Einfach und elegant.
Maesk
10

Wenn Sie JetBrains Idea IDE (und Derivate) verwenden, können Sie mehrere Zeilen auswählen, mit der rechten Maustaste auf das Kontextmenü klicken und dann Git -> Verlauf zur Auswahl anzeigen. Sie sehen eine Liste der Commits, die sich auf die ausgewählten Zeilen ausgewirkt haben:

Geben Sie hier die Bildbeschreibung ein

warvariuc
quelle
Dies funktionierte besser als die anderen Antworten für mich (mit IntelliJ). Es hat eine Weile gedauert, alle Revisionen zu laden, aber das Warten hat sich gelohnt.
Steve Chambers
2

Ab Git 2.23 können Sie Git Blame --ignore-rev verwenden

Für das in der Frage gegebene Beispiel wäre dies:

git blame -L10,+1 src/options.cpp --ignore-rev fe25b6d

(Es ist jedoch eine Trickfrage, da fe25b6d die erste Revision der Datei ist!)

Michael Platings
quelle
1

Aufbauend auf der Antwort von Will Shepard enthält seine Ausgabe doppelte Zeilen für Commits, bei denen keine Änderung vorgenommen wurde. Sie können diese also wie folgt filtern (mithilfe dieser Antwort ).

LINE=1 FILE=a; for commit in $(git rev-list HEAD $FILE); do git blame -n -L$LINE,+1 $commit -- $FILE; done | sed '$!N; /^\(.*\)\n\1$/!P; D'

Beachten Sie, dass ich das REVS-Argument entfernt habe und dies auf das Root-Commit zurückgeht. Dies ist auf die obige Beobachtung von Max Nanasy zurückzuführen.

DavidN
quelle
1

Aufbauend auf der Antwort von DavidN möchte ich der umbenannten Datei folgen:

LINE=8 FILE=Info.plist; for commit in $(git log --format='%h%%' --name-only --follow -- $FILE | xargs echo | perl -pe 's/\%\s/,/g'); do hash=$(echo $commit | cut -f1 -d ','); fileMayRenamed=$(echo $commit | cut -f2 -d ','); git blame -n -L$LINE,+1 $hash -- $fileMayRenamed; done | sed '$!N; /^\(.*\)\n\1$/!P; D'

ref: Den Verlauf des Umbenennens von Dateien im Git-Protokoll gut anzeigen

Bill Chan
quelle
0

Ich benutze dieses kleine Bash-Skript, um einen Schuldverlauf zu betrachten.

Erster Parameter: zu betrachtende Datei

Nachfolgende Parameter: An git schuld übergeben

#!/bin/bash
f=$1
shift
{ git log --pretty=format:%H -- "$f"; echo; } | {
  while read hash; do
    echo "--- $hash"
    git blame $@ $hash -- "$f" | sed 's/^/  /'
  done
}

Sie können Schuldparameter wie -L 70, + 10 angeben, aber es ist besser, die Regex-Suche nach Git-Schuld zu verwenden, da sich Zeilennummern normalerweise im Laufe der Zeit "ändern".

erdrosselt
quelle
0

Aufbauend auf der Antwort von stangls habe ich dieses Skript als git-bh in meinen PATH (auch unter Windows) eingefügt:

Dadurch kann ich nach allen Commits suchen, bei denen es um ein Wort ging:

git bh path/to/myfile myWord

Skript:

#!/bin/bash
f=$1
shift
csha=""
{ git log --pretty=format:%H -- "$f"; echo; } | {
  while read hash; do
    res=$(git blame -L"/$1/",+1 $hash -- "$f" 2>/dev/null | sed 's/^/  /')
    sha=${res%% (*}
    if [[ "${res}" != "" && "${csha}" != "${sha}" ]]; then
      echo "--- ${hash}"
      echo "${res}"
      csha="${sha}"
    fi
  done
}
VonC
quelle