Ich habe zwei Repositories. In einem nehme ich Änderungen an der Datei vor ./hello.test
. Ich übertrage die Änderungen und erstelle einen Patch aus diesem Commit mit git format-patch -1 HEAD
. Jetzt habe ich ein zweites Repository, das eine Datei enthält, die den gleichen Inhalt wie hello.test hat, aber in einem anderen Verzeichnis unter einem anderen Namen abgelegt ist : ./blue/red/hi.test
. Wie gehe ich vor, um den oben genannten Patch auf die hi.test
Datei anzuwenden ? Ich habe es versucht, git am --directory='blue/red' < patch_file
aber das beschwert sich natürlich darüber, dass die Dateien nicht den gleichen Namen haben (was Git meiner Meinung nach egal war?). Ich weiß, dass ich das Diff wahrscheinlich bearbeiten könnte, um es auf diese bestimmte Datei anzuwenden, aber ich suche nach einer Befehlslösung.
100
Antworten:
Sie können den Patch mithilfe
git diff
despatch
Dienstprogramms erstellen und dann mit dem Dienstprogramm anwenden, mit dem Sie die Datei angeben können, auf die Sie das Diff anwenden möchten.Beispielsweise:
quelle
am
oder tun könnenapply
, aber ich kann es nicht finden. Wenn Sie feststellen, dass Sie Änderungen häufig duplizieren, gibt es möglicherweise eine bessere Lösung für die Verwendung von Submodulen oder für eine beliebige Sprache Ihrer Wahl, um Code freizugeben (z. B. können Sie in Ruby den doppelten Code als Juwel extrahieren).Es gibt eine einfache Lösung, die weder manuelle Patch-Bearbeitung noch externes Skript umfasst.
Im ersten Repository (dies kann auch einen Bereich von Commits exportieren, verwenden
-1
Sie , wenn Sie nur ein Commit auswählen möchten):Im zweiten Repository:
Anstatt
--relative
in zu verwendengit format-patch
, besteht eine andere Lösung darin, die-p<n>
Option ingit am
zu verwenden, umn
Verzeichnisse aus dem Pfad der Patches zu entfernen, wie in einer Antwort auf eine ähnliche Frage erwähnt .Es ist auch möglich,
git format-patch --relative <committish>
ohne das auszuführen--stdout
, und es wird eine Reihe von.patch
Dateien generiert . Diese Dateien können dann direktgit am
mit eingezogen werdengit am --directory blue/red/ path/to/*.patch
.quelle
--directory
Option anscheinend erfordert, dass Sie den vollständigen Pfad des Verzeichnisses relativ zum Repo-Stamm angeben. So etwas wie "--directory=./
chdir'd in ein Unterverzeichnis im Repo" funktioniert nicht.--3way
hilft beidoes not exist in index
:git am --3way --directory (relative-path) (patch)
-k
Taste in beiden Befehlen, um die erste Zeile der Festschreibungsnachricht nicht zu entfernen.--3way
hilft nicht nur bei Fehlern, die im Index nicht vorhanden sind (wie von @nobar hervorgehoben), sondern ermöglicht Ihnen auch, Zusammenführungskonflikte sauber zu behandeln. Anstatt in Konflikt stehende Dateien unberührt zu lassen, wird ein Konfliktblock hinzugefügt, der dann gelöst werden kann.Beantwortung meiner eigenen Frage mit einem Skript, das genau dies tut: https://github.com/mprpic/apply-patch-to-file
Anstatt die Patch-Datei manuell zu ändern, fordert sie den Benutzer zur Eingabe der Zieldatei auf, ändert den Patch und wendet ihn auf das Repo an, in dem Sie sich gerade befinden.
quelle
Aufbauend auf der Antwort von @georgebrock habe ich folgende Lösung verwendet:
Erstellen Sie zunächst die Patch-Dateien wie gewohnt (z. B.
git format-patch commitA..commitB
).Stellen Sie dann sicher, dass Ihr Ziel-Repository sauber ist (es sollten keine geänderten oder nicht verfolgten Dateien vorhanden sein), und wenden Sie die Patches wie folgt an:
Für jede Patch-Datei wird ein Fehler wie "Fehler: XYZ existiert nicht im Index" angezeigt. Sie können diese Patch-Datei jetzt manuell anwenden:
Sie müssen diese drei Schritte für jede Patch-Datei ausführen.
Dadurch bleibt die ursprüngliche Festschreibungsnachricht usw. erhalten, ohne dass ein spezieller
git format-patch
Befehl erforderlich ist oder die Patch-Dateien bearbeitet werden müssen.quelle
git format-patch -1 commitA --stdout > thing.diff
; (2) Bearbeiten Sie die Patch-Datei, bis sie das tut, was ich brauche. (3) Zu festschreibender Text,git am --3way thing.diff
der den Vorteil hat, dass Sie die Teile des Patches akzeptieren können, die saubergit
angewendet werden , und den Standardprozess zur Konfliktlösung für die Teile verwenden können, die dies nicht tun.Ich verstehe, dass die beiden Dateien in Ihrer Situation genau gleich sind, daher ist der Patch wahrscheinlich erfolgreich.
Jedoch im Fall , dass Sie einen Patch auf ein ähnliches anwenden, aber nicht genau die gleiche Datei, oder möchten Sie eine interaktive Patching tun, werden Sie drei Wege - Merge verwenden.
Angenommen, Sie haben die Datei geändert
A
, bezeichnen sieA~1
als die vorherige Version und möchten den Unterschied zwischenA~1
toA
auf File anwendenB
.Öffnen Sie ein Drei-Wege-Zusammenführungswerkzeug, z. B. Beyond Compare. Der Pfad des linken Fensters ist
A
, das mittlere Feld ist der gemeinsame Vorfahr, also ist der PfadA~1
der Pfad des rechten FenstersB
. Dann wird die untere Tafel zeigt das Ergebnis der Anwendung den diff zwischenA~1
bisA
zu DateiB
.Die folgende Abbildung veranschaulicht die Idee.
quelle
Zu Ihrer Information: Ich hatte kürzlich Probleme beim Versuch, einen Patch von Github herunterzuladen und auf eine lokale Datei anzuwenden (was eine "Überschreibung" an einem neuen Speicherort war).
git am
Ich würde den Patch auch nicht anwenden, da die Datei "nicht im Index" oder "schmutzig" war. Aber ich fand , dass der einfachepatch
Befehl könnte den Patch anwenden. Ich wurde aufgefordert, den Namen der zu patchenden Datei anzugeben.Habe den Job sowieso erledigt ...
quelle