Mehrmals bin ich auf die Aussage gestoßen, dass Git sie verfolgen kann, wenn Sie eine einzelne Funktion von einer Datei in eine andere verschieben. In diesem Eintrag heißt es beispielsweise : "Linus sagt, wenn Sie eine Funktion von einer Datei in eine andere verschieben, zeigt Git Ihnen den Verlauf dieser einzelnen Funktion während der Verschiebung an."
Aber ich bin mir ein bisschen bewusst, was Git unter der Haube zu bieten hat, und ich sehe nicht, wie das möglich ist. Ich frage mich also ... ist das eine korrekte Aussage? Und wenn ja, wie ist das möglich?
Mein Verständnis ist, dass Git den Inhalt jeder Datei als Blob speichert und jeder Blob eine global eindeutige Identität hat, die sich aus dem SHA-Hash seines Inhalts und seiner Größe ergibt. Git repräsentiert dann Ordner als Bäume. Alle Dateinameninformationen gehören zum Baum, nicht zum Blob, sodass eine Umbenennung einer Datei beispielsweise als Änderung eines Baums und nicht eines Blobs angezeigt wird.
Wenn ich also eine Datei namens "foo" mit 20 Funktionen und eine Datei namens "bar" mit 5 Funktionen habe und eine der Funktionen von foo in bar verschiebe (was 19 bzw. 6 ergibt), Wie kann Git erkennen, dass ich diese Funktion von einer Datei in eine andere verschoben habe?
Nach meinem Verständnis würde dies dazu führen, dass 2 neue Blobs existieren (einer für den modifizierten foo und einer für den modifizierten Balken). Mir ist klar, dass ein Unterschied berechnet werden kann, um zu zeigen, dass die Funktion von einer Datei in die andere verschoben wurde. Aber ich sehe nicht, wie der Verlauf der Funktion möglicherweise mit bar anstelle von foo in Verbindung gebracht werden könnte (jedenfalls nicht automatisch).
Wenn Git tatsächlich in einzelne Dateien schauen und einen Blob pro Funktion berechnen würde (was verrückt / unmöglich wäre, weil man wissen müsste, wie man eine mögliche Sprache analysiert), könnte ich sehen, wie dies möglich sein könnte.
Also ... ist die Aussage richtig oder nicht? Und wenn es richtig ist, was fehlt dann in meinem Verständnis?
Antworten:
Diese Funktionalität wird durch bereitgestellt
git blame -C <file>
.Die
-C
Option veranlasst git, Übereinstimmungen zwischen dem Hinzufügen oder Löschen von Textblöcken in der zu überprüfenden Datei und den in denselben Änderungssätzen geänderten Dateien zu finden. Zusätzliche-C -C
oder-C -C -C
erweitern Sie die Suche.Versuchen Sie es selbst in einem Test-Repo mit
git blame -C
und Sie werden sehen, dass der Codeblock, den Sie gerade verschoben haben, aus der Originaldatei stammt, zu der er gehört.Von der
git help blame
Handbuchseite:quelle
git blame -C10 file3
Dann wurde das erste Commit angezeigt, bei dem diese Zeile zu Datei1 hinzugefügt wurde, aber ich wollte unbedingt das letzte Commit sehen, das diese Zeile verschoben hat (dh das Commit, das die Zeile zu Datei2 verschoben hat.) Gibt es eine Möglichkeit, dies zu erreichen? Ich habe einige nützliche Informationen erhaltengit log -S'my interesting line'
, aber immer noch nicht ganz das, wonach ich suche.git blame
dafür geeignet wäre.git blame
würde zeigen , nur die letzte Änderung an der Linie (ob eine Bewegung oder auch nicht), wo mein Kommentar gefragt für die „letzte begehen , die diese Zeile bewegt “ (vermutlich nach einige weitere Commits Änderung der Linie gemacht wurden).-CC
und-CCC
scheint nicht zu funktionieren ... hiergit version 2.15.0.rc0
muss ich den isolierten-C
Schalter mehrmals separat übergeben, damit er den dokumentierten Effekt hat. Die Dokumentation irgendwie zeigt dies, zumindest implizit. Diese Antwort und andere Kommentare weisen jedoch darauf hin, dass dies in der Vergangenheit funktioniert hat. Hmmm.Ab Git 2.15
git diff
unterstützt jetzt die Erkennung von verschobenen Linien mit der--color-moved
Option. Es funktioniert für Verschiebungen zwischen Dateien.Dies funktioniert natürlich für kolorierte Terminalausgänge. Soweit ich das beurteilen kann, gibt es keine Möglichkeit, Bewegungen im Nur-Text-Patch-Format anzugeben, aber das ist sinnvoll.
Versuchen Sie es mit dem Standardverhalten
Der Befehl nimmt auch Optionen, die derzeit
no
,default
,plain
,zebra
unddimmed_zebra
(Verwenden Siegit help diff
die aktuellen Optionen und die Beschreibungen zu bekommen). Zum Beispiel:In Bezug auf , wie es geschehen ist, kann man ein gewisses Verständnis von aufzulesen diesem E - Mail Austausch vom Autor der Funktionalität .
quelle
--color-moved
Option standardmäßig angewendet wird?git config
zum Einstellen verwendendiff.colorMoved
.Ein Teil dieser Funktionalität befindet sich in
git gui blame
(+ Dateiname). Es zeigt eine Anmerkung der Zeilen einer Datei, die jeweils angibt, wann sie erstellt und wann sie zuletzt geändert wurde. Bei der Codeverschiebung in einer Datei wird das Festschreiben der Originaldatei als Erstellung und das Festschreiben angezeigt, bei dem es als letzte Änderung zur aktuellen Datei hinzugefügt wurde . Versuch es.Was ich wirklich möchte, ist,
git log
als Argument zusätzlich zu einem Dateipfad einen Zeilennummernbereich anzugeben und dann den Verlauf dieses Codeblocks anzuzeigen. Es gibt keine solche Option, wenn die Dokumentation richtig ist. Ja, nach Linus 'Aussage würde auch ich denken, dass ein solcher Befehl leicht verfügbar sein sollte.quelle
git-gui
Paket verfügbar .git verfolgt Umbenennungen überhaupt nicht . Ein Umbenennen ist nur ein Löschen und Hinzufügen, das ist alles. Alle Tools, die Umbenennungen anzeigen, rekonstruieren sie aus diesen Verlaufsinformationen.
Das Umbenennen von Tracking-Funktionen ist daher eine einfache Angelegenheit, bei der die Unterschiede aller Dateien in jedem Commit nachträglich analysiert werden. Daran ist nichts besonders Unmögliches; Das vorhandene Umbenennungs-Tracking behandelt bereits 'Fuzzy'-Umbenennungen, bei denen einige Änderungen an der Datei vorgenommen und umbenannt werden. Dies erfordert das Betrachten des Inhalts der Dateien. Es wäre eine einfache Erweiterung, auch nach Funktionsumbenennungen zu suchen.
Ich weiß jedoch nicht, ob die Basis-Git-Tools dies tatsächlich tun - sie versuchen, sprachneutral zu sein, und die Funktionsidentifikation ist sehr viel nicht sprachneutral.
quelle
Das
git diff
zeigt Ihnen, dass bestimmte Zeilen verschwunden sindfoo
und wieder aufgetaucht sindbar
. Wenn diese Dateien im selben Commit keine weiteren Änderungen enthalten, ist die Änderung leicht zu erkennen.Ein intellektueller
git
Kunde kann Ihnen zeigen, wie Zeilen von einer Datei in eine andere verschoben wurden. Eine sprachbewusste IDE könnte diese Änderung einer bestimmten Funktion zuordnen.Ähnliches passiert, wenn eine Datei umbenannt wird. Es verschwindet nur unter einem Namen und erscheint unter einem anderen wieder, aber jedes vernünftige Tool kann es bemerken und als Umbenennung darstellen.
quelle
-CC
oder hat es-CCC
jemals funktioniert? Sie scheinen jetzt sicherlich nicht (Git-Version 2.15.0.rc0)git version 2.7.4
undgit help blame
weiß-C
: "Wenn diese Option dreimal angegeben wird, sucht der Befehl in jedem Commit zusätzlich nach Kopien aus anderen Dateien."