1812 Stimmen

Wie kann ich in Git selektiv Änderungen aus einem anderen Zweig zusammenführen oder auswählen?

Ich verwende Git für ein neues Projekt, das zwei parallele - aber derzeit experimentelle - Entwicklungszweige hat:

  • master Import der bestehenden Codebasis plus einige Änderungen, bei denen ich mir im Allgemeinen sicher bin
  • exp1 : Versuchszweig #1
  • exp2 : Versuchszweig #2

exp1 y exp2 stehen für zwei sehr unterschiedliche Architekturansätze. Solange ich nicht weitergekommen bin, kann ich nicht wissen, welcher Ansatz (wenn überhaupt) funktionieren wird. Wenn ich in einem Zweig Fortschritte mache, habe ich manchmal Bearbeitungen, die im anderen Zweig nützlich wären, und möchte genau diese zusammenführen.

Was ist der beste Weg, um selektive Änderungen von einem Entwicklungszweig in einen anderen zusammenzuführen und dabei alles andere zurückzulassen?

Ansätze, die ich in Betracht gezogen habe:

  1. git merge --no-commit gefolgt von der manuellen Freigabe einer großen Anzahl von Bearbeitungen, die ich nicht zwischen den Zweigen austauschen möchte.

  2. Manuelles Kopieren von gemeinsamen Dateien in ein temporäres Verzeichnis, gefolgt von git checkout um in den anderen Zweig zu wechseln und dann mehr manuelles Kopieren aus dem temporären Verzeichnis in den Arbeitsbaum.

  3. Eine Abwandlung des obigen Beispiels. Verzichten Sie auf die exp Zweigen und verwenden Sie zwei zusätzliche lokale Repositories für Experimente. Dies macht das manuelle Kopieren von Dateien viel einfacher.

Alle drei Ansätze erscheinen mühsam und fehleranfällig. Ich hoffe, dass es einen besseren Ansatz gibt; so etwas wie einen Filterpfad-Parameter, der die git-merge wählerischer.

1186voto

Susheel Javadi Punkte 2874

Ich hatte genau das gleiche Problem, das Sie oben beschrieben haben. Aber ich fand ce die Antwort deutlicher zu erläutern.

Zusammenfassung:

  • Prüfen Sie den Pfad/die Pfade des Zweigs, den Sie zusammenführen wollen,

     $ git checkout source_branch -- <paths>...
    
    Hint: It also works without `--` like seen in the linked post.
  • oder zum selektiven Zusammenführen von Hunks

     $ git checkout -p source_branch -- <paths>...

Alternativ können Sie auch zurücksetzen und dann mit der Option -p ,

    $ git reset <paths>...
    $ git add -p <paths>...
  • Endlich festlegen

     $ git commit -m "'Merge' these changes"

574voto

1800 INFORMATION Punkte 125009

Sie verwenden die . Befehl, um einzelne Übertragungen aus einem Zweig zu erhalten.

Wenn die gewünschte(n) Änderung(en) nicht in einzelnen Commits enthalten sind, verwenden Sie die hier gezeigte Methode, um Aufteilung des Commits in einzelne Commits . Grob gesagt, verwenden Sie git rebase -i um die ursprüngliche Übergabe zur Bearbeitung zu erhalten, dann git reset HEAD^ um Änderungen selektiv rückgängig zu machen, dann git commit um dieses Bit als neue Übertragung in der Historie zu speichern.

Es gibt eine weitere schöne Methode hier im Red Hat Magazine, wo sie die git add --patch oder möglicherweise git add --interactive die es Ihnen ermöglicht, nur Teile eines Hunks hinzuzufügen, wenn Sie verschiedene Änderungen in eine einzelne Datei aufteilen möchten (suchen Sie auf dieser Seite nach "split").

Nachdem Sie die Änderungen aufgeteilt haben, können Sie sich nun die gewünschten Änderungen heraussuchen.

466voto

alvinabad Punkte 4337

Um selektiv Dateien aus einem Zweig in einen anderen Zweig zusammenzuführen, führen Sie

git merge --no-ff --no-commit branchX

wobei branchX ist der Zweig, aus dem Sie in den aktuellen Zweig zusammenführen wollen.

El --no-commit die Dateien, die von Git zusammengeführt wurden, ohne sie tatsächlich zu übertragen. Dadurch haben Sie die Möglichkeit, die zusammengeführten Dateien nach Belieben zu ändern und sie dann selbst zu übertragen.

Je nachdem, wie Sie die Dateien zusammenführen wollen, gibt es vier Möglichkeiten:

1) Sie wollen eine echte Verschmelzung.

In diesem Fall akzeptieren Sie die zusammengeführten Dateien so, wie Git sie automatisch zusammengeführt hat, und übertragen sie dann.

2) Es gibt einige Dateien, die Sie nicht zusammenführen wollen.

Sie möchten beispielsweise die Version im aktuellen Zweig beibehalten und die Version im Zweig, aus dem Sie zusammenführen, ignorieren.

Um die Version im aktuellen Zweig auszuwählen, führen Sie aus:

git checkout HEAD file1

Damit wird die Version von file1 im aktuellen Zweig und überschreiben die file1 automatisch von Git zusammengeführt.

3) Wenn Sie die Version in ZweigX (und nicht eine echte Zusammenführung) wünschen.

Laufen:

git checkout branchX file1

Damit wird die Version von file1 en branchX und überschreiben file1 automatisch von Git zusammengeführt.

4) Der letzte Fall ist, wenn Sie nur bestimmte Zusammenführungen in file1 .

In diesem Fall können Sie die geänderte file1 direkt, aktualisieren Sie sie auf die Version, die Sie für die file1 zu werden, und sich dann zu verpflichten.

Wenn Git eine Datei nicht automatisch zusammenführen kann, meldet es die Datei als " unmerged "und erstellen Sie eine Kopie, in der Sie die Konflikte manuell lösen müssen.


Um dies anhand eines Beispiels näher zu erläutern, nehmen wir an, Sie möchten Folgendes zusammenführen branchX in den aktuellen Zweig:

git merge --no-ff --no-commit branchX

Sie führen dann die git status um den Status der geänderten Dateien anzuzeigen.

Zum Beispiel:

git status

# On branch master
# Changes to be committed:
#
#       modified:   file1
#       modified:   file2
#       modified:   file3
# Unmerged paths:
#   (use "git add/rm <file>..." as appropriate to mark resolution)
#
#       both modified:      file4
#

Donde file1 , file2 y file3 sind die Dateien, die Git erfolgreich automatisch zusammengeführt hat.

Dies bedeutet, dass Veränderungen in der master y branchX für all diese drei Dateien wurden konfliktfrei miteinander kombiniert.

Sie können überprüfen, wie die Zusammenführung durchgeführt wurde, indem Sie die git diff --cached ;

git diff --cached file1
git diff --cached file2
git diff --cached file3

Wenn Sie eine Zusammenführung unerwünscht finden, können Sie

  1. die Datei direkt bearbeiten
  2. speichern
  3. git commit

Wenn Sie nicht fusionieren wollen file1 und die Version im aktuellen Zweig beibehalten wollen

ausführen.

git checkout HEAD file1

Wenn Sie nicht fusionieren wollen file2 und wollen nur die Version in branchX

ausführen.

git checkout branchX file2

Wenn Sie wollen file3 automatisch zusammengeführt werden sollen, tun Sie nichts.

Git hat es zu diesem Zeitpunkt bereits zusammengeführt.

file4 oben ist ein fehlgeschlagener Merge von Git. Das bedeutet, dass es in beiden Zweigen Änderungen gibt, die in derselben Zeile auftreten. In diesem Fall müssen Sie die Konflikte manuell auflösen. Sie können das Zusammenführen verwerfen, indem Sie die Datei direkt bearbeiten oder den Befehl checkout für die Version im gewünschten Zweig ausführen file4 zu werden.

Schließlich sollten Sie nicht vergessen git commit .

119voto

nosatalian Punkte 6419

Mir gefallen die oben genannten Ansätze nicht. Die Verwendung von Cherry-Pick ist großartig, um eine einzelne Änderung auszuwählen, aber es ist mühsam, wenn man alle Änderungen mit Ausnahme der schlechten einbringen will. Hier ist mein Ansatz.

Es gibt keine --interactive Argument, das Sie an git merge übergeben können.

Hier ist die Alternative:

Sie haben einige Änderungen im Zweig 'feature' und möchten einige, aber nicht alle, auf eine nicht zu schlampige Art und Weise nach 'master' übertragen (d.h. Sie möchten nicht jede einzelne Änderung auswählen und übertragen)

git checkout feature
git checkout -b temp
git rebase -i master

# Above will drop you in an editor and pick the changes you want ala:
pick 7266df7 First change
pick 1b3f7df Another change
pick 5bbf56f Last change

# Rebase b44c147..5bbf56f onto b44c147
#
# Commands:
# pick = use commit
# edit = use commit, but stop for amending
# squash = use commit, but meld into previous commit
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#

git checkout master
git pull . temp
git branch -d temp

Also verpacken Sie das einfach in ein Shell-Skript, ändern Sie master in $to und ändern Sie feature in $from und Sie sind startklar:

#!/bin/bash
# git-interactive-merge
from=$1
to=$2
git checkout $from
git checkout -b ${from}_tmp
git rebase -i $to
# Above will drop you in an editor and pick the changes you want
git checkout $to
git pull . ${from}_tmp
git branch -d ${from}_tmp

116voto

Chronial Punkte 59424

Es gibt noch einen anderen Weg zu gehen:

git checkout -p

Es ist eine Mischung aus git checkout y git add -p und könnte genau das sein, wonach Sie suchen:

   -p, --patch
       Interactively select hunks in the difference between the <tree-ish>
       (or the index, if unspecified) and the working tree. The chosen
       hunks are then applied in reverse to the working tree (and if a
       <tree-ish> was specified, the index).

       This means that you can use git checkout -p to selectively discard
       edits from your current working tree. See the “Interactive Mode”
       section of git-add(1) to learn how to operate the --patch mode.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X