822 Stimmen

Ist es möglich, Dateien in Git zu verschieben/umzubenennen und ihren Verlauf beizubehalten?

Ich möchte einen Projektunterbaum in Git umbenennen/verschieben, indem ich ihn von

/project/xyz

zu

/components/xyz

Wenn ich eine einfache git mv project components dann wird die gesamte Commit-Historie für die xyz project verloren geht. Gibt es eine Möglichkeit, dies so zu verschieben, dass die Historie erhalten bleibt?

14 Stimmen

5 Stimmen

Ich möchte nur anmerken, dass ich gerade das Verschieben von Dateien über das Dateisystem getestet habe, und nach dem Übertragen (über intellij) kann ich dann den gesamten Verlauf sehen (einschließlich des Verlaufs, wenn er sich an einem anderen Ort befand), wenn ich den Verlauf (wieder in intellij) ansehe. Ich gehe davon aus, dass intellij nichts Besonderes tut, um das zu tun, also ist es schön zu wissen, dass zumindest die Historie nachvollzogen werden kann.

0 Stimmen

Für die Regeln, denen Git bei der Erkennung einer Verzeichnisumbenennung folgt, siehe meine Antwort unten

740voto

Troels Thomsen Punkte 10875

Git erkennt Umbenennungen, anstatt die Operation mit dem Commit zu persistieren, d.h. ob Sie git mv o mv spielt keine Rolle.

El log Befehl nimmt eine --follow Argument, das die Historie vor einer Umbenennungsoperation fortsetzt, d.h. es sucht nach ähnlichen Inhalten unter Verwendung von Heuristiken.

Um den gesamten Verlauf abzurufen, verwenden Sie den folgenden Befehl:

git log --follow ./path/to/file

11 Stimmen

Es wäre schön, wenn man das --follow nicht bräuchte, aber ich denke, das wird reichen müssen. Vielen Dank für Ihre Antwort.

71 Stimmen

Ich vermute, dass dies mit der Leistung zusammenhängt. Wenn Sie nicht den gesamten Verlauf benötigen, dauert das Scannen des Inhalts sicher länger. Der einfachste Weg ist, einen Alias einzurichten git config alias.logf "log --follow" und schreiben Sie einfach git logf ./path/to/file .

0 Stimmen

Aber welchen Pfad geben Sie an, den alten oder den neuen Pfad? Und wenn es der alte Pfad ist, woher wissen Sie dann, dass Sie den alten Pfad angeben müssen?

192voto

Tuntable Punkte 2760

No.

Die kurze Antwort lautet NO . Es ist nicht möglich, eine Datei in Git umzubenennen und sich den Verlauf zu merken. Und es ist eine Qual.

Man munkelt, dass git log --follow --find-copies-harder funktioniert, aber bei mir funktioniert es nicht, selbst wenn es keine Änderungen am Inhalt der Datei gibt und die Verschiebungen mit git mv .

(Ursprünglich habe ich Eclipse verwendet, um Pakete in einem Arbeitsgang umzubenennen und zu aktualisieren, was Git vielleicht verwirrt hat. Aber das ist eine sehr übliche Vorgehensweise. --follow scheint zu funktionieren, wenn nur ein mv durchgeführt und anschließend eine commit und die mv ist nicht allzu weit).

Linus sagt, dass man den gesamten Inhalt eines Softwareprojekts ganzheitlich verstehen soll und nicht einzelne Dateien verfolgen muss. Nun, leider kann mein kleines Gehirn das nicht leisten.

Sie ist sehr ärgerlich dass so viele Leute gedankenlos die Behauptung wiederholt haben, dass Git automatisch Bewegungen verfolgt. Sie haben meine Zeit verschwendet. Git macht so etwas nicht. Git ist so konzipiert(!), dass es Bewegungen überhaupt nicht verfolgt.

Meine Lösung besteht darin, die Dateien an ihren ursprünglichen Speicherort zurückzubenennen. Ändern Sie die Software, um sie an die Versionskontrolle anzupassen. Mit Git müssen Sie es anscheinend nur beim ersten Mal richtig "git".

Leider funktioniert das nicht mit Eclipse, das anscheinend die --follow . git log --follow zeigt manchmal nicht den vollständigen Verlauf von Dateien mit komplizierten Umbenennungsvorgängen, obwohl git log tut. (Ich weiß nicht, warum.)

(Es gibt einige zu clevere Hacks, die zurückgehen und alte Arbeit wieder aufnehmen, aber sie sind eher beängstigend. Siehe GitHub-Gist: emiller/git-mv-mit-geschichte .)

Kurz gesagt: Wenn Subversion macht das falsch ist, dann ist es auch falsch, dass Git dies tut - dies ist keine (falsche!) Funktion, Es ist ein Fehler.

3 Stimmen

Ich glaube, Sie haben Recht. Ich habe gerade versucht, php-cs-fixer zu verwenden, um den Quellcode für mein Laravel 5-Projekt neu zu formatieren, aber es besteht darauf, die Großschreibung der Namespace-Klauseln so zu ändern, dass sie mit dem Kleinbuchstaben-Wert des App-Ordners übereinstimmt. Aber Namespaces (oder composer autoloads) funktionieren nur mit CamelCase. Ich muss die Großschreibung des Ordners in App ändern, aber das führt dazu, dass meine Änderungen verloren gehen. Dies ist das trivialste aller Beispiele, aber es zeigt, dass die Git-Heuristik nicht in der Lage ist, selbst den einfachsten Namensänderungen zu folgen (--follow und --find-copies-harder sollten die Regel sein, nicht die Ausnahme).

17 Stimmen

Git -1, subversion +1

6 Stimmen

Stimmt das noch? Das ist ein weiterer Grund für mich, vorerst bei tfs zu bleiben, denn die Historie einer verschobenen/umbenannten Datei zu behalten ist ein Muss in einem großen Projekt.

120voto

Øystein Steimler Punkte 1479

Sie ist möglich um eine Datei umzubenennen und die Historie intakt zu halten, obwohl es dazu führt, dass die Datei in der gesamten Historie des Repositorys umbenannt wird. Dies ist wahrscheinlich nur etwas für obsessive Git-Log-Liebhaber und hat einige schwerwiegende Auswirkungen, einschließlich dieser:

  • Sie könnten eine gemeinsame Historie überschreiben, was das wichtigste DON'T bei der Verwendung von Git ist. Wenn jemand anderes das Repository geklont hat, machen Sie es auf diese Weise kaputt. Sie müssen dann neu klonen, um Kopfschmerzen zu vermeiden. Das mag in Ordnung sein, wenn die Umbenennung wichtig genug ist, aber Sie müssen sich das gut überlegen - Sie könnten am Ende eine ganze Open-Source-Gemeinschaft verärgern!
  • Wenn Sie die Datei unter ihrem alten Namen in der Repository-Historie referenziert haben, brechen Sie damit frühere Versionen. Um dies zu beheben, müssen Sie ein wenig mehr Aufwand betreiben. Es ist nicht unmöglich, nur mühsam und möglicherweise nicht lohnenswert.

Da Sie immer noch bei mir sind, sind Sie wahrscheinlich ein Solo-Entwickler, der eine völlig isolierte Datei umbenennt. Verschieben wir eine Datei mit filter-tree !

Angenommen, Sie wollen eine Datei verschieben old in einen Ordner dir und geben ihm den Namen new

Dies könnte geschehen mit git mv old dir/new && git add -u dir/new aber das macht die Geschichte kaputt.

Stattdessen:

git filter-branch --tree-filter 'if [ -f old ]; then mkdir dir && mv old dir/new; fi' HEAD

wird wiederherstellen. jede Übergabe im Zweig, wobei der Befehl in den Ticks für jede Iteration ausgeführt wird. Dabei kann eine Menge schief gehen. Normalerweise prüfe ich, ob die Datei vorhanden ist (andernfalls ist sie noch nicht zum Verschieben da) und führe dann die notwendigen Schritte aus, um den Baum nach meinem Geschmack zu gestalten. Dabei können Sie sich durch die Dateien bewegen, um Verweise auf die Datei zu ändern usw. Viel Spaß dabei! :)

Nach Abschluss des Vorgangs wird die Datei verschoben und das Protokoll bleibt intakt. Sie fühlen sich wie ein Piraten-Ninja.

Außerdem ist mkdir dir natürlich nur notwendig, wenn Sie die Datei in einen neuen Ordner verschieben. Die wenn verhindert, dass dieser Ordner zu einem früheren Zeitpunkt erstellt wird, als Ihre Datei bereits existiert.

68 Stimmen

Als obsessiver Git-Log-Liebhaber würde ich mich nicht darauf einlassen. Die Dateien wurden zu diesen Zeitpunkten nicht so benannt, daher spiegelt die Geschichte eine nie existierende Situation wider. Wer weiß, welche Tests in der Vergangenheit kaputt gegangen sind! Das Risiko, frühere Versionen zu zerstören, ist es in so gut wie jedem Fall nicht wert.

9 Stimmen

@Vincent Sie haben völlig Recht, und ich habe versucht, so deutlich wie möglich zu machen, dass diese Lösung unwahrscheinlich ist. Ich denke auch, dass wir in diesem Fall über zwei Bedeutungen des Wortes "Geschichte" sprechen, ich schätze beide.

9 Stimmen

Ich finde, es gibt Situationen, in denen man das brauchen könnte. Sagen wir, ich habe etwas in meinem eigenen Zweig entwickelt, das ich nun stromaufwärts einfließen lassen möchte. Aber ich stelle fest, dass der Dateiname nicht angemessen ist, also ändere ich ihn für meinen gesamten persönlichen Zweig. Auf diese Weise kann ich eine saubere und korrekte Historie führen und habe von Anfang an den richtigen Namen.

49voto

Erik Hesselink Punkte 2320
git log --follow [file]

zeigt Ihnen den Verlauf der Umbenennungen an.

42 Stimmen

Es scheint, dass Sie nur die Umbenennung bestätigen müssen, bevor Sie mit der Änderung der Datei beginnen. Wenn Sie die Datei (in der Shell) verschieben und sie dann ändern, ist alles verloren.

29 Stimmen

@yoyo: Das liegt daran, dass Git Umbenennungen nicht verfolgt, sondern sie erkennt. A git mv macht grundsätzlich eine git rm && git add . Es gibt Optionen wie -M90 / --find-renames=90 eine Datei als umbenannt zu betrachten, wenn sie zu 90% identisch ist.

28voto

James M. Greene Punkte 1193

Das tue ich:

git mv {old} {new}
git add -u {new}

4 Stimmen

Das -u scheint bei mir nichts zu bewirken, soll es den Verlauf aktualisieren?

1 Stimmen

Vielleicht möchten Sie das Verhalten von -A stattdessen? Siehe auch hier: git-scm.com/docs/git-add

1 Stimmen

Die Dateien werden zwar hinzugefügt, aber der Verlauf wird nicht aktualisiert, so dass "git log file name" den vollständigen Verlauf anzeigt. Der vollständige Verlauf wird nur angezeigt, wenn Sie noch die Option --follow verwenden.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X