Wie füge ich Änderungen zu einer einzelnen Datei zusammen, anstatt Commits zusammenzuführen?


383

Ich habe zwei Zweige (A und B) und möchte eine einzelne Datei aus Zweig A mit einer entsprechenden einzelnen Datei aus Zweig B zusammenführen.



27
In den meisten Antworten auf diesen anderen Beitrag geht es darum, wie Commits und nicht Dateien selektiv zusammengeführt werden . Dies macht die ausgewählte Antwort falsch. Die Frage bleibt unbeantwortet.


Diese Antwort ist der richtige Weg, IMO. git diff branch_name > patch git apply patch. stackoverflow.com/a/9473543/1091853
blamb

Antworten:


631

Ich bin auf das gleiche Problem gestoßen. Um genau zu sein, habe ich zwei Zweige Aund Bmit den gleichen Dateien, aber in einigen Dateien eine andere Programmierschnittstelle. Jetzt wurden die Dateimethoden f, die unabhängig von den Schnittstellenunterschieden in den beiden Zweigen sind, im Zweig geändert B, aber die Änderung ist für beide Zweige wichtig. Daher muss ich nur die Datei fder Verzweigung Bin die Datei fder Verzweigung zusammenführen A.

Ein einfacher Befehl hat das Problem für mich bereits gelöst, wenn ich davon ausgehe, dass alle Änderungen in beiden Zweigen festgeschrieben sind Aund B:

git checkout A

git checkout --patch B f

Der erste Befehl wechselt in den Zweig A, in den ich die BVersion der Datei zusammenführen möchte f. Der zweite Befehl patcht die Datei fmit fvon HEADvon B. Sie können sogar einzelne Teile des Patches akzeptieren / verwerfen. Anstatt dass BSie hier ein Commit angeben können, muss es nicht sein HEAD.

Community bearbeiten : Wenn die Datei fauf Bexistiert nicht auf Anoch, lassen Sie dann die --patchOption. Andernfalls erhalten Sie eine "Keine Änderung". Botschaft.


10
Dies funktioniert nur, wenn Sie eine Datei aktualisieren möchten. Was ist, wenn ich eine neue Datei von Zweig B zu Zweig A hinzufügen möchte?
Umair A.

25
@UmairAshraf Sie sollten in der Lage sein, eine neue Datei von B nach A hinzuzufügen, indem Sie die Option --patch entfernen.
Bbak

9
Hmmm ... wenn ich das versuche, bekomme ich die Meldung "keine Änderungen", aber es gibt eindeutig Änderungen. OK, ich musste mich in dem Ordner befinden, in dem sich die entsprechende Datei befand. Bearbeiten: Dies könnte möglicherweise meine Lieblingslösung für ein Problem sein, das ich auf stackoverflow gesehen habe :-D
bot_bot

2
Ich musste es benutzen git checkout --patch B -- f, um das zum Laufen zu bringen.
user545424

8
Sie müssen nur hinzufügen, dass Sie, wenn Sie mehrere Änderungen (Hunks) in der Datei haben und alle Änderungen vornehmen möchten ,a während der interaktiven Phase drücken können , anstatt yjedes Mal zu drücken . Oder verwenden Sie git checkout B -- fstattdessen den Befehl.
Dmitry Gonchar

17

Folgendes mache ich in diesen Situationen. Es ist ein Kludge, aber es funktioniert gut für mich.

  1. Erstellen Sie einen weiteren Zweig basierend auf Ihrem Arbeitszweig.
  2. git pull / git führt die Revision (SHA1) zusammen, die die zu kopierende Datei enthält. Dadurch werden alle Ihre Änderungen zusammengeführt, aber wir verwenden diesen Zweig nur, um die eine Datei abzurufen.
  3. Beheben Sie Konflikte usw. Untersuchen Sie Ihre Datei.
  4. Kasse Ihrer Arbeitsstelle
  5. Überprüfen Sie die aus Ihrer Zusammenführung festgeschriebene Datei.
  6. Verpflichte es.

Ich habe versucht zu patchen und meine Situation war zu hässlich dafür. Kurz gesagt würde es so aussehen:

Arbeitszweig: Ein experimenteller Zweig: B (enthält file.txt mit Änderungen, die ich einfügen möchte.)

git checkout A

Erstellen Sie einen neuen Zweig basierend auf A:

git checkout -b tempAB

Füge B in tempAB zusammen

git merge B

Kopieren Sie den sha1-Hash der Zusammenführung:

git log

commit 8dad944210dfb901695975886737dc35614fa94e
Merge: ea3aec1 0f76e61
Author: matthewe <matthewe@matthewe.com>
Date:   Wed Oct 3 15:13:24 2012 -0700

Merge branch 'B' into tempAB

Kasse Ihrer Arbeitsstelle:

git checkout A

Überprüfen Sie Ihre reparierte Datei:

git checkout 7e65b5a52e5f8b1979d75dffbbe4f7ee7dad5017 file.txt

Und da solltest du es haben. Übernehmen Sie Ihr Ergebnis.


3
Also müssen wir das alles tun, um nur eine einzige Datei zusammenzuführen? Wäre es nicht einfacher, die Datei zu kopieren und in den anderen Zweig
Robin

1
@Robin wahrscheinlich nicht, da durch das Zusammenführen die Änderungen in der Datei erhalten bleiben, die sich zwischen Zweig A und B unterscheiden. Durch das Kopieren der Datei werden zusätzliche Unterschiede zwischen Ihrem Arbeitszweig A und dem, was Sie von B einbringen möchten, überschrieben, die möglicherweise nicht enthalten sind diese Einträge / Änderungen. zB hat sich der Verdächtige zunächst auf andere Weise Aabgelenkt B. Durch das Kopieren werden diese Unterschiede überschrieben.
Blamb

14

Dies verwendet das interne Difftool von Git. Vielleicht ein bisschen Arbeit, aber einfach.

#First checkout the branch you want to merge into
git checkout <branch_to_merge_into>

#Then checkout the file from the branch you want to merge from
git checkout <branch_to_merge_from> -- <file> 

#Then you have to unstage that file to be able to use difftool
git reset HEAD <file> 

#Now use difftool to chose which lines to keep. Click on the mergebutton in difftool
git difftool

#Save the file in difftool and you should be done.

1
Um die Verwendung von --(leere Argumentbezeichnung) zu verdeutlichen, sagen git checkout docs: ARGUMENT DISAMBIGUATION : "Verwenden git checkout -- <pathspec>Sie diese Option , wenn Sie diese Pfade aus dem Index auschecken möchten ." Dies liegt daran, dass Sie sowohl einen Zweig als auch eine Datei / einen Pfad mit demselben Namen haben können. In solchen Fällen fordert git standardmäßig dazu auf, den Zweig auszuchecken, anstatt Sie zu fragen, ob der Zweig oder der Pfad ausgecheckt werden soll, wenn beide vorhanden sind. Wenn --jedoch git vorausgeht, wird stattdessen die Datei / der Pfad ausgecheckt.
SherylHohman

8

Ich fand diesen Ansatz einfach und nützlich: Wie man bestimmte Dateien aus einem anderen Zweig "zusammenführt"

Wie sich herausstellt, versuchen wir es zu sehr. Unsere gute Freundin Git Checkout ist das richtige Werkzeug für den Job.

git checkout source_branch <paths>...

Wir können git checkout einfach den Namen des Feature-Zweigs A und die Pfade zu den spezifischen Dateien geben, die wir unserem Hauptzweig hinzufügen möchten.

Bitte lesen Sie den gesamten Artikel für mehr Verständnis


2
Dies überschreibt die Dateien, es führt sie nicht zusammen
Alex G

Für Sie hängt es möglicherweise davon ab, was Sie tun und was Sie erreichen möchten. Die Idee hier ist, Zweig B ist Gabelung von A, Sie ändern 4 Dateien in B, möchten aber nur 2 von B nach A zusammenführen. Regelmäßiges Zusammenführen würde alle 4 zusammenführen, hier können Sie auswählen. Dies kann so aussehen, als ob sie überschrieben wurden, da B wesentlich neuere Dateien enthält. Sie müssen Ihre Erfahrung mit einigen Beweisen untermauern.
Pawel Cioch

Ich bin damit einverstanden, dass es überschreibt. Ich denke, Sie wollten die -pOption in diesem Befehl verwenden. Was dann alle Teile in Ihrer Arbeitsbaumdatei überschreibt, die zuvor von dem Zweig umgeleitet wurden, von dem Sie ausgecheckt haben, bevor sich der Patch leider ändert.
Blamb

Nun, die Idee war von 2009, es besteht die Möglichkeit, dass sich eine neue Version von git anders verhält und -p oder irgendetwas anderes benötigt, aber als ich sie veröffentlichte, funktionierte sie für mich, aber vielleicht war es mir auch egal, ob die Dateien überschrieben wurden Die neueste Version war das, was ich brauchte
Pawel Cioch


3

Mit dem folgenden Befehl (1) wird die Datei des richtigen Zweigs verglichen, und Master (2) fragt Sie interaktiv, welche Änderungen angewendet werden sollen.

Git Checkout - Patch Master


0

Meine Bearbeitung wurde abgelehnt, daher füge ich hier an, wie Änderungen aus einem Remote-Zweig zusammengeführt werden.

Wenn Sie dies nach einer falschen Zusammenführung tun müssen, können Sie Folgendes tun:

# If you did a git pull and it broke something, do this first
# Find the one before the merge, copy the SHA1
git reflog
git reset --hard <sha1>

# Get remote updates but DONT auto merge it
git fetch github 

# Checkout to your mainline so your branch is correct.
git checkout develop 

# Make a new branch where you'll be applying matches
git checkout -b manual-merge-github-develop

# Apply your patches
git checkout --patch github/develop path/to/file
...

# Merge changes back in
git checkout develop
git merge manual-merge-github-develop # optionally add --no-ff

# You'll probably have to
git push -f # make sure you know what you're doing.

0

Angenommen, B ist der aktuelle Zweig:

$ git diff A <file-path> > patch.tmp
$ git apply patch.tmp -R

Beachten Sie, dass dies nur Änderungen an der lokalen Datei betrifft. Sie müssen sich danach festlegen.


Für mich erzeugt dies einenerror: <file-path>: already exists in working directory
kontur

Sie sollten eine Datei oder einen Dateipfad im aktuellen Verzeichnis angeben. Ich benutzegit diff Branch_A <file-path, filename> -- hash_commit > file_name.temp
R.Chatsiri

0

Sie können die alte Version der zusammenzuführenden Datei auschecken, unter einem anderen Namen speichern und dann ausführen, was auch immer Ihr Zusammenführungstool für die beiden Dateien ist.

z.B.

git show B:src/common/store.ts > /tmp/store.ts (wobei B der Filialname / Commit / Tag ist)

meld src/common/store.ts /tmp/store.ts


0

Ich werde es als tun

git format-patch branch_old..branch_new file

Dadurch wird ein Patch für die Datei erstellt.

Wenden Sie den Patch auf target branch_old an

git am blahblah.patch


Können Sie den Patch für zusätzliche Sicherheit leicht untersuchen?
XavierStuvw
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.