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.

1voto

matt Punkte 481428

Ich werde mich auf die Teilmenge dieses Problems konzentrieren, die für mich von Interesse war: Ich habe zwei Zweige und möchte diese pseudo-zusammenführen eine Datei aus dem einen in das andere.

(Ich sage "Pseudo-Merge", weil ich keinen Merge-Commit brauche oder will; ich will nur die Beiträge beider Versionen der Datei kombinieren, und zwar so, wie ich es für richtig halte.)

Mein Ansatz stützt sich auf den Ansatz, der in https://stackoverflow.com/a/39916536/341994 . Leider wurde diese Frage als Duplikat geschlossen (meiner Meinung nach zu Unrecht: Es handelt sich nicht um ein Duplikat dieser Frage, und es ist falsch, zu antworten und als Duplikat zu schließen, was der Beantworter hier getan hat). Aber es gibt einige Dinge, die mit dieser Antwort nicht in Ordnung sind, also habe ich den Ansatz modernisiert und aufgeräumt. Anstelle von checkout y reset verwende ich restore und ich mache mir nicht die Mühe, etwas zu tun, was ich nicht tun muss.

Okay, stellen Sie sich vor, ich habe drei Dateien:

$ ls
a   b   f

Ich möchte aber nur eine von ihnen pseudo-verschmelzen, a , von otherbranch . Schauen wir sie uns an, um zu sehen, wie die Situation aussehen wird. Hier ist meine Version:

$ cat a
line one
line two
line three
line four
line five

Hier ist die Version von otherbranch:

$ git show otherbranch:a
line one
line two edited
line three
line four
line five
line six

Der Trick dabei ist, dass wir den Index als Notizblock verwenden (dafür ist er ja schließlich da). Wir beginnen also (SCHRITT 1), indem wir sicherstellen, dass unsere Version in den Index kopiert wird:

$ git add a

Jetzt (SCHRITT 2) können wir verwenden restore um die Version zu holen von otherbranch (Heutzutage, restore ist besser als checkout da sie uns deutlicher sprechen lässt):

$ git restore --source otherbranch a

Auf den ersten Blick sieht das schlecht aus. Wir haben jetzt unser a komplett mit der Version von otherbranch wie Sie sehen können:

$ cat a
line one
line two edited
line three
line four
line five
line six

Aber keine Sorge! Die vorherige Version von a ist immer noch im Index, wie Sie sehen können:

$ git diff a
diff --git a/a b/a
index abf51fa..333614b 100644
--- a/a
+++ b/a
@@ -1,6 +1,7 @@
 line one
-line two
+line two edited
 line three
 line four
 line five
+line six

Sehr gut, jetzt sind wir bereit für den entscheidenden Schritt (SCHRITT 3). Wir machen einen interaktives Patch add unserer Datei aus dem Arbeitsbaum in den Index.

Wir könnten sagen git add -p a um den interaktiven Patch-Prozess zu starten, bei dem die Hunks nacheinander gefüttert werden. Aber in diesem Fall gibt es nur einen Hunk, und ich will ihn sowieso bearbeiten, also sage ich:

$ git add --e a

Das Ergebnis ist, dass wir eine Patchdatei mit Diffs in unserem Editor öffnen! Sie sieht folgendermaßen aus:

 line one
-line two
+line two edited
 line three
 line four
 line five
+line six

Durch sorgfältige Bearbeitung können wir nun entscheiden, welche Teile wir akzeptieren wollen und welche nicht. Wir wollen "Zeile sechs" akzeptieren, aber nicht "Zeile zwei bearbeitet". Wir editieren also so, dass es so aussieht:

 line one
 line two
 line three
 line four
 line five
+line six

Wir schließen den Editor und der Patch wird auf die Indexversion von a angewendet. Aber wir sind noch nicht ganz fertig! Die otherbranch Version von a befindet sich noch im Arbeitsbaum:

$ cat a
line one
line two edited
line three
line four
line five
line six

Die Version, die uns gefällt, steht im Index, schon vergessen? Um sie zu erhalten, (SCHRITT 4) rufen wir einfach git restore schlicht und einfach (auch das ist die moderne Art; restore ist schöner als reset und kann sich auf eine einzige Datei beziehen):

$ git restore a

Jetzt ist unser a korrekt, und wir sind fertig:

$ cat a
line one
line two
line three
line four
line five
line six

Wir könnten uns jetzt verpflichten, aber das müssen wir nicht; wir haben erreicht, was wir uns vorgenommen haben.

1voto

djanowski Punkte 5258

Was ich will: Interaktiv Hunks aus einem Zweig (der mehrere unsaubere Commits hatte) in einen sauberen Commit in einem neuen Zweig übernehmen.

git diff + git apply funktioniert nicht, wenn Sie Binärdateien in diesem Diff haben.

Mein Ansatz:

# New branch from a clean starting point, e.g. master
git checkout new-clean-branch origin/master

# Get all changes from the messy branch
# (quote the star so your shell doesn't expand it)
git checkout messy-branch -- '*'

# Unstage ("un-add") everything
git restore --staged .

# Interactively add hunks to be staged for commit
git add -p

0voto

Shoniisra Punkte 177

Wenn Sie ein Gitkraken Benutzer Hier haben Sie einen kleinen Leitfaden

Zusammengefasst:

  1. Wechseln Sie zu dem Zweig, in den Sie die Änderungen einbringen wollen. (z.B. entwickeln)
  2. Klicken Sie mit der rechten Maustaste auf den Zweig mit den neuen Änderungen und wählen Sie die Option " Cherrypick Commit "Option (z. B. Merkmal-ABC).
  3. Akzeptieren Sie schließlich und prüfen Sie, ob es Konflikte gibt.

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