Ich versuche gerade ein ziemlich bulliges Git-Merge-Manöver. Ein Problem, auf das ich stoße, ist, dass ich einige Änderungen an einem Code in meiner Zweigstelle vorgenommen habe, mein Kollege diesen Code jedoch in eine neue Datei in seiner Zweigstelle verschoben hat. Als ich das tat git merge my_branch his_branch
, bemerkte git nicht, dass der Code in der neuen Datei mit dem alten identisch war, und daher sind keine meiner Änderungen vorhanden.
Was ist der einfachste Weg, um meine Änderungen erneut auf den Code in den neuen Dateien anzuwenden? Ich werde nicht zu viele Probleme haben, herauszufinden, welche Commits erneut angewendet werden müssen (ich kann sie nur verwenden git log --stat
). Aber soweit ich das beurteilen kann, gibt es keine Möglichkeit, git dazu zu bringen, die Änderungen erneut auf die neuen Dateien anzuwenden. Das Einfachste, was ich derzeit sehe, ist, die Änderungen manuell erneut anzuwenden, was nicht nach einer guten Idee aussieht.
Ich weiß, dass git Blobs erkennt, keine Dateien. Es muss also eine Möglichkeit geben, dies zu sagen: "Wenden Sie diese genaue Codeänderung aus diesem Commit an, außer nicht dort, wo sie war, sondern wo sie sich jetzt in dieser neuen Datei befindet."
--rename-threshold
Möglichkeit, die erforderliche Ähnlichkeit zu optimieren.Antworten:
Ich hatte ein ähnliches Problem und habe es behoben, indem ich meine Arbeit neu ausgerichtet habe, um sie an die Organisation der Zieldatei anzupassen.
Angenommen, Sie haben Änderungen
original.txt
an Ihrem Zweig (demlocal
Zweig) vorgenommen, der jedoch am Hauptzweig inoriginal.txt
einen anderen kopiert wurdecopy.txt
. Diese Kopie wurde in einem Commit erstellt, das wir Commit nennenCP
.Sie möchten alle Ihre lokalen Änderungen, Commits
A
undB
darunter, die vorgenommen wurdenoriginal.txt
, auf die neue Datei anwendencopy.txt
.Erstellen Sie am Wegpunkt
move
Ihrer Änderungen mit einen Wegwerfzweiggit branch move X
. Das heißt, setzen Sie denmove
Zweig auf CommitX
, den vor den Commits, die Sie zusammenführen möchten. Dies ist höchstwahrscheinlich das Commit, von dem aus Sie zur Implementierung Ihrer Änderungen verzweigt haben. Wie Benutzer @digory doo unten schrieb, können Sie tungit merge-base master local
, um zu findenX
.Geben Sie in diesem Zweig den folgenden Umbenennungsbefehl aus:
Dadurch wird die Datei umbenannt. Beachten Sie, dass
copy.txt
dies zu diesem Zeitpunkt noch nicht in Ihrem Baum vorhanden war.Übernehmen Sie Ihre Änderung (wir nennen diese Festschreibung
MV
).Sie können Ihre Arbeit jetzt neu aufbauen auf
move
:Dies sollte problemlos funktionieren und Ihre Änderungen werden
copy.txt
in Ihrer lokalen Niederlassung übernommen.Jetzt möchten oder müssen Sie nicht unbedingt ein Commit haben
MV
im Verlauf Ihres Hauptzweigs haben, da der Verschiebevorgang zu einem Konflikt mit dem Kopiervorgang beim FestschreibenCP
im Hauptzweig führen kann.Sie müssen Ihre Arbeit nur erneut neu starten und den Verschiebevorgang wie folgt verwerfen:
... wo
CP
ist das Commit wocopy.txt
wurde in der anderen Niederlassung eingeführt. Dadurch werden alle Änderungen zusätzlichcopy.txt
zumCP
Commit neu berechnet . Jetzt ist Ihrlocal
Zweig genau so, als hätten Sie ihn immer geändertcopy.txt
und nichtoriginal.txt
, und Sie können weiterhin mit anderen zusammenführen.Es ist wichtig, dass die Änderungen angewendet werden
CP
oder auf andere Weisecopy.txt
nicht vorhanden sind und die Änderungen wieder angewendet werdenoriginal.txt
.Hoffe das ist klar. Diese Antwort kommt zu spät, kann aber für andere nützlich sein.
quelle
patch
(was möglicherweise auch viel Arbeit erfordert), und deshalb hielt ich es für interessant, sie zu zeigen. Beachten Sie außerdem, dass ich in meinem Fall mehr Zeit gebraucht habe, um die Antwort zu schreiben, als die Änderungen tatsächlich anzuwenden. In welchem Schritt würden Sie eine Zusammenführung empfehlen? und warum? Der einzige Unterschied, den ich sehe, besteht darin, dass ich durch erneutes Basieren ein temporäres Commit mache, das später verworfen wird (CommitMV
), was nur bei Zusammenführungen nicht möglich ist.Sie können den Patch jederzeit mit
git diff
(odergit format-patch
) generieren, dann die Dateinamen im Patch manuell bearbeiten und mitgit apply
(oder) anwendengit am
) .Kurz gesagt, die einzige Möglichkeit, wie es automatisch funktioniert, besteht darin, dass die Umbenennungserkennung von git herausfinden kann, dass die alten und neuen Dateien dasselbe sind - was sich so anhört, als wären sie nicht wirklich in Ihrem Fall, sondern nur ein Teil davon. Es ist wahr, dass git Blobs verwendet, keine Dateien, aber ein Blob ist nur der Inhalt einer gesamten Datei, ohne den angehängten Dateinamen und Metadaten. Wenn Sie also einen Codeabschnitt zwischen zwei Dateien verschoben haben, sind diese nicht wirklich derselbe Blob - der Rest des Blob-Inhalts ist unterschiedlich, nur der gemeinsame Block.
quelle
git format-patch
für ein Commit arbeiten kann. Ingit format-patch SHA1
diesem Fall werden eine ganze Reihe von Patch-Dateien für den gesamten Verlauf generiert. Aber ich denke, esgit show SHA1 > diff.patch
wird genauso gut funktionieren.-1
Option. Die normale Betriebsart für Format-Patch ist beispielsweise ein Revisionsbereichorigin/master..master
, sodass Sie problemlos eine Patch-Serie vorbereiten können.git apply
undgit am
sind zu wählerisch, weil sie die gleichen Zeilennummern wollen. Aber ich bin derzeit mit dem UNIX-patch
Befehl erfolgreich.Hier ist eine Zusammenführungslösung , bei der ein Zusammenführungskonflikt beim Umbenennen und Bearbeiten auftritt und mit mergetool gelöst wird, wobei die richtigen 3 Zusammenführungsquelldateien erkannt werden.
Nachdem eine Zusammenführung aufgrund einer gelöschten Datei fehlgeschlagen ist, von der Sie feststellen, dass sie umbenannt und bearbeitet wurde:
Durchgang:
Erstellen Sie eine Datei.txt:
Erstellen Sie einen Zweig, den Sie später bearbeiten werden:
Erstellen Sie die Umbenennung und bearbeiten Sie sie auf dem Master:
Zum Zweig wechseln und dort auch bearbeiten:
Versuch, Master zusammenzuführen:
Beachten Sie, dass der Konflikt schwer zu lösen ist - und dass Dateien umbenannt wurden. Abbrechen, die Umbenennung nachahmen:
Versuchen Sie es erneut:
Toll! Das Zusammenführen führt zu einem "normalen" Konflikt, der mit mergetool gelöst werden kann:
quelle
B.txt -> C.txt
undA.txt -> B.txt
git die Zusammenführungskonflikte nicht automatisch korrekt zuordnen konnte (es wurden Zusammenführungskonflikte zwischen altB.txt
und neu angezeigtB.txt
). Mit dieser Methode befinden sich die Zusammenführungskonflikte jetzt zwischen den richtigen Dateien.