git: Übernehmen Sie die durch Festschreiben in einem Repo eingeführten Änderungen auf ein anderes Repo

115

Ich habe einen repo1und repo2auf einem lokalen Computer. Sie sind sehr ähnlich, aber letzteres ist eine Art anderer Zweig ( repo1wird nicht mehr gepflegt).

/path/to/repo1 $ git log HEAD~5..HEAD~4
<some_sha> Add: Introduce feature X

Wie Änderungen verpflichten beantragen <some_sha>in repo1zu repo2?

Muss ich einen Patch vorbereiten oder ist es möglich, einen cherry-pickzwischen den Repos zu machen?

Wie wäre es, dasselbe zu tun, aber für eine Reihe von Commits?

Takeshin
quelle
2
Kannst du nicht einfach von repo1 zu repo2 ziehen?
zwol
Für den etwas spezifischeren Fall, in dem Sie Änderungen auf eine Datei oder Dateien anwenden möchten
Braham Snyder

Antworten:

31

Als Hack können Sie versuchen, das Rezept für den Vergleich von Commits in zwei verschiedenen Repositorys auf der GitTips-Seite zu ändern , z.

GIT_ALTERNATE_OBJECT_DIRECTORIES=../repo/.git/objects \
git cherry-pick $(git --git-dir=../repo/.git rev-parse --verify <commit>)

Wo ../repoist der Pfad zum anderen Repository?

Mit modernem Git können Sie mit Cherry-Pick mehrere Revisionen und Revisionsbereiche verwenden .

Das $(git --git-dir=../repo/.git rev-parse --verify <commit>) ist hier, um <commit>(zum Beispiel HEADoder v0.2, oder master~2, was Werte im zweiten Repository sind, aus dem Sie kopieren) in die SHA-1-ID des Commits zu übersetzen. Wenn Sie SHA-1 einer Änderung kennen, die Sie auswählen möchten, ist dies nicht erforderlich.

Beachten Sie jedoch, dass Git das Kopieren von Objekten aus dem Quell-Repository überspringen kann, da es nicht weiß, dass das alternative Objekt-Repository für einen Vorgang nur vorübergehend ist. Möglicherweise müssen Sie Objekte aus dem zweiten Repository kopieren mit:

GIT_ALTERNATE_OBJECT_DIRECTORIES=../repo/.git/objects git repack -a -d -f

Dadurch werden die aus dem zweiten Repository ausgeliehenen Objekte in den ursprünglichen Repository-Speicher verschoben

Nicht getestet.


Eine nicht so hackige Lösung ist es, der knittl Antwort zu folgen :

  • Wechseln Sie zum zweiten Repository, aus dem Sie Commits kopieren möchten, und generieren Sie Patches aus Commits, mit denen Sie Commits durchführen möchten git format-patch
  • Kopieren Sie optional Patches (0001- * usw.) in Ihr Repository
  • Verwenden Sie git am --3waydiese Option , um Patches anzuwenden
Jakub Narębski
quelle
1
Funktioniert gut. Wenn Sie Probleme mit dem Commit haben, setzen Sie HEAD auf Git zurück. git add. '.
Gumik
5
Das ist großartig - wie würden Sie eine Reihe von Commits durchführen? nur sha1 ... sha2?
Hvgotcodes
Ich bekomme auch fatal: unable to read tree ...aber nachdem git reset HEAD^alles gut funktioniert
jmarceli
@hvgotcodes Es hat bei mir einfach funktioniert, indem der Bereich als übergeben wurde, <commit>aber der rev-parse --verifyBefehl mag es nicht, da er nur einzelne Festschreibungswerte akzeptiert. Da jedoch cherry-picksowohl Einzel- als auch Bereichs-Commit-Werte akzeptiert werden, frage ich: Warum wird dies rev-parsebenötigt?
Chuim
1
@Chuim: wird git rev-parsebenötigt, wenn Sie ein beziehen möchten begehen , indem er seine ref-basierten Namen in anderen Repository, zum Beispiel master, HEAD^^oder so ähnlich; rev-parse verwandelt es in eine universelle SHA-1-Kennung.
Jakub Narębski
207

Sie möchten diesen Patch wahrscheinlich verwenden git format-patchund dann git amauf Ihr Repository anwenden.

/path/to/1 $ git format-patch sha1^..sha1
/path/to/1 $ cd /path/to/2
/path/to/2 $ git am -3 /path/to/1/0001-…-….patch

Oder in einer Zeile:

/path/to/2 $ git --git-dir=/path/to/1/.git format-patch --stdout sha1^..sha1 | git am -3
stricken
quelle
9
Diese Lösung erwies sich als einfacher und sicherer als die akzeptierte Antwort der direkten Kirschernte mit GIT_ALTERNATE_OBJECT_DIRECTORIES(diese würde mein Repository beschädigen).
Chuim
2
Bei Konflikten funktioniert dies nicht, da die Commits im anderen Zweig nicht gefunden werden können.
Roger Far
2
Das Hinzufügen --ignore-whitespacezum git amBefehl kann Konflikte lösen und vermeiden, dass eine 3-Wege-Zusammenführung durchgeführt werden muss
Hugheth
97

Sie können dies tun, cherry-pickwenn Sie das zweite Repo als Fernbedienung zum ersten (und dann fetch) hinzufügen .

wRAR
quelle
11
Das ist eigentlich der richtige Weg, es zu tun.
Wilbert
5
Das fühlt sich auch für mich richtig an. Und ich habe es einfach benutzt und es hat gut für mich funktioniert.
Ricky Nelson
10
Ich würde eher sagen: mach git fetch [remote-name]im zweiten Repo und dann git cherry-pick [sha1].
5
Dieser Ansatz hat für mich großartig funktioniert, danke. Da das zweite Repo ebenfalls lokal war, musste beim Hinzufügen als Remote nur ein Datei-URI verwendet werden.
Palimpsestor
2
In meinem Fall habe ich zwei Klone eines gigantischen Remote-Git-Repositorys (um paralleles Arbeiten zu ermöglichen), was bedeutet, dass der gesamte Verlauf bereits zweimal heruntergeladen und auf meiner Festplatte gespeichert wurde. Wenn ich beide auch als Fernbedienung hinzufügen müsste, würde dies noch zwei zusätzliche Kopien desselben Verlaufs erstellen und möglicherweise Synchronisierungen zwischen ihnen erfordern, bevor ich dazu in der Lage wäre cherry-pick. Auch wenn es sich wie der "richtige" Weg anfühlt, ist es nicht immer der praktischste.
Chuim