So führen Sie bestimmte Dateien aus Git-Zweigen zusammen

179

Ich habe 2 Git-Zweige branch1 und branch2 und möchte file.py in branch2 in file.py in branch1 und nur diese Datei zusammenführen.

Im Wesentlichen möchte ich nur an der Datei.py in branch1 arbeiten, aber den Befehl merge nutzen. Was ist der beste Weg, dies zu tun?

rwolst
quelle

Antworten:

206

Wenn Inhalte file.pyaus Zweig2 eingehen , die nicht mehr für Zweig1 gelten , müssen einige Änderungen ausgewählt und andere belassen werden . Führen Sie zur vollständigen Kontrolle eine interaktive Zusammenführung mit dem --patchSchalter durch:

$ git checkout --patch branch2 file.py

Im Abschnitt zum interaktiven Modus in der Manpage git-add(1)werden die zu verwendenden Tasten erläutert:

y - stage this hunk
n - do not stage this hunk
q - quit; do not stage this hunk nor any of the remaining ones
a - stage this hunk and all later hunks in the file
d - do not stage this hunk nor any of the later hunks in the file
g - select a hunk to go to
/ - search for a hunk matching the given regex
j - leave this hunk undecided, see next undecided hunk
J - leave this hunk undecided, see next hunk
k - leave this hunk undecided, see previous undecided hunk
K - leave this hunk undecided, see previous hunk
s - split the current hunk into smaller hunks
e - manually edit the current hunk
? - print help

Der Befehl split ist besonders nützlich.

pdp
quelle
3
Wie können wir Patches verwenden und gleichzeitig ein Merge-Tool verwenden? anstelle der Schlüssel Sachen
Gabriel
@Gabriel Ich habe Git sogar mit Patch-Dateien und Tarballs verwendet, weil es so einfach ist, ein Repo ( git init <dir>) zu erstellen und es schließlich wegzuwerfen ( rm -r <dir>).
pdp
105

Obwohl dies an sich keine Zusammenführung ist , wird manchmal der gesamte Inhalt einer anderen Datei in einem anderen Zweig benötigt. Der Blog-Beitrag von Jason Rudolph bietet eine einfache Möglichkeit, Dateien von einem Zweig in einen anderen zu kopieren. Wenden Sie die Technik wie folgt an:

$ git checkout branch1 # ensure in branch1 is checked out and active
$ git checkout branch2 file.py

Jetzt file.pyist jetzt in branch1 .

Мати Тернер
quelle
91
Einfach, aber das ist eigentlich keine Zusammenführung . Es überschreibt nur file.pymit allem, was in Zweig 2 ist.
Greg Hewgill
Was ist, wenn Sie die Datei von Zweig1 zu Zweig2 zurückführen? Du wirst Konflikte bekommen!
Amir
Behält dies die Commit-Historie bei?
C2H50H
18

Keine der anderen aktuellen Antworten "führt" die Dateien tatsächlich zusammen, als ob Sie den Befehl "Zusammenführen" verwenden würden. (Im besten Fall müssen Sie die Unterschiede manuell auswählen.) Wenn Sie die Zusammenführung mithilfe der Informationen eines gemeinsamen Vorfahren nutzen möchten, können Sie ein Verfahren befolgen, das auf dem im Abschnitt "Erweitertes Zusammenführen" des Git enthaltenen Verfahren basiert Referenzhandbuch.

Für dieses Protokoll gehe ich davon aus, dass Sie die Datei 'path / to / file.txt' von origin / master in HEAD zusammenführen möchten - ändern Sie sie entsprechend. (Sie müssen sich nicht im obersten Verzeichnis Ihres Repositorys befinden, aber es hilft.)

# Find the merge base SHA1 (the common ancestor) for the two commits:
git merge-base HEAD origin/master

# Get the contents of the files at each stage
git show <merge-base SHA1>:path/to/file.txt > ./file.common.txt
git show HEAD:path/to/file.txt > ./file.ours.txt
git show origin/master:path/to/file.txt > ./file.theirs.txt

# You can pre-edit any of the files (e.g. run a formatter on it), if you want.

# Merge the files
git merge-file -p ./file.ours.txt ./file.common.txt ./file.theirs.txt > ./file.merged.txt

# Resolve merge conflicts in ./file.merged.txt
# Copy the merged version to the destination
# Clean up the intermediate files

Die Git-Zusammenführungsdatei sollte alle Ihre Standard-Zusammenführungseinstellungen für die Formatierung und dergleichen verwenden.

Beachten Sie auch, dass Sie direkt mit der Datei arbeiten können, wenn Ihre "unsere" die Arbeitskopie ist und Sie nicht übermäßig vorsichtig sein möchten:

git merge-base HEAD origin/master
git show <merge-base SHA1>:path/to/file.txt > ./file.common.txt
git show origin/master:path/to/file.txt > ./file.theirs.txt
git merge-file path/to/file.txt ./file.common.txt ./file.theirs.txt
RM
quelle
15

Sind alle Änderungen file.pyin branch2ihrem eigenen Commits, getrennt von Änderungen an anderen Dateien? Wenn ja, können Sie einfach cherry-pickdie Änderungen umstellen:

git checkout branch1
git cherry-pick <commit-with-changes-to-file.py>

Andernfalls mergewird nicht über einzelne Pfade gearbeitet. Sie können auch einfach einen git diffPatch mit file.pyÄnderungen von branch2und git applyan erstellen branch1:

git checkout branch2
git diff <base-commit-before-changes-to-file.py> -- file.py > my.patch
git checkout branch1
git apply my.patch

quelle
8

Sie können stashund stash popdie Datei:

git checkout branch1
git checkout branch2 file.py
git stash
git checkout branch1
git stash pop
Martin G.
quelle
Dadurch wird branch1 / file.py mit dem Inhalt von branch2 / file.py anstelle einer Zusammenführung überschrieben, die einen zu lösenden Zusammenführungskonflikt auslösen sollte.
plumSemPy
2

Um nur die Änderungen von branch2 zusammenzuführen file.py, lassen Sie die anderen Änderungen verschwinden .

git checkout -B wip branch2
git read-tree branch1
git checkout branch2 file.py
git commit -m'merging only file.py history from branch2 into branch1'
git checkout branch1
git merge wip

Beim Zusammenführen wird niemals eine andere Datei angezeigt. Möglicherweise müssen Sie die Kassen "-f", wenn die Bäume unterschiedlich genug sind.

Beachten Sie, dass branch1 so aussieht, als wäre alles in der Geschichte von branch2 bis zu diesem Punkt zusammengeführt worden, was möglicherweise nicht Ihren Wünschen entspricht. Eine bessere Version der ersten Kasse oben ist wahrscheinlich

git checkout -B wip `git merge-base branch1 branch2`

In diesem Fall sollte die Commit-Nachricht wahrscheinlich auch sein

git commit -m"merging only $(git rev-parse branch2):file.py into branch1"
jthill
quelle
0

Ich bin in der gleichen Situation, ich möchte eine Datei aus einem Zweig zusammenführen, der viele Commits auf 2 Zweigen hat. Ich habe viele Möglichkeiten ausprobiert und andere, die ich im Internet gefunden habe, und alle sind fehlgeschlagen (weil der Commit-Verlauf komplex ist), also entscheide ich mich, meinen Weg zu gehen (den verrückten Weg).

git merge <other-branch>
cp file-to-merge file-to-merge.example
git reset --hard HEAD (or HEAD^1 if no conflicts happen)
cp file-to-merge.example file-to-merge
Trac Nguyen
quelle
0

Was ich getan habe, ist ein bisschen manuell, aber ich:

  1. Die Zweige normal zusammengeführt; Die Zusammenführung mit rückgängig gemacht revert;
  2. Alle meine Dateien wurden ausgecheckt HEAD~1, um ihren Status beim Zusammenführungs-Commit zu ermitteln.
  3. Ich habe meine Commits neu erstellt, um diesen Hacker aus dem Commit-Verlauf zu verbergen.

Hässlich? Ja. Leicht zu erinnern? Auch ja.

Lucas Lima
quelle