Git Merge Master in Feature Branch

1016

Nehmen wir an, wir haben die folgende Situation in Git:

  1. Ein erstelltes Repository:

    mkdir GitTest2
    cd GitTest2
    git init
    
  2. Einige Änderungen im Master finden statt und werden festgeschrieben:

    echo "On Master" > file
    git commit -a -m "Initial commit"
    
  3. Feature1 hat vom Master abgezweigt und einige Arbeiten sind erledigt:

    git branch feature1
    git checkout feature1
    echo "Feature1" > featureFile
    git commit -a -m "Commit for feature1"
    
  4. Währenddessen wird ein Fehler im Master-Code entdeckt und ein Hotfix-Zweig eingerichtet:

    git checkout master
    git branch hotfix1
    git checkout hotfix1
    
  5. Der Fehler wurde im Hotfix-Zweig behoben und wieder mit dem Master zusammengeführt (möglicherweise nach einer Pull-Anfrage / Code-Überprüfung):

    echo "Bugfix" > bugfixFile
    git commit -a -m "Bugfix Commit"
    git checkout master
    git merge --no-ff hotfix1
    
  6. Die Entwicklung von Feature1 wird fortgesetzt:

    git checkout feature1
    

Angenommen, ich benötige den Hotfix in meinem Feature-Zweig, möglicherweise weil der Fehler auch dort auftritt. Wie kann ich dies erreichen, ohne die Commits in meinem Feature-Zweig zu duplizieren?

Ich möchte verhindern, dass zwei neue Commits in meinem Feature-Zweig angezeigt werden, die keinen Bezug zur Feature-Implementierung haben. Dies scheint mir besonders wichtig zu sein, wenn ich Pull-Anfragen verwende: Alle diese Commits werden auch in die Pull-Anfrage aufgenommen und müssen überprüft werden, obwohl dies bereits geschehen ist (da sich der Hotfix bereits im Master befindet).

Ich kann kein git merge master --ff-only: "fatal: Nicht schnell vorspulen, abbrechen.", Aber ich bin mir nicht sicher, ob mir das geholfen hat.

theomega
quelle
8
Wenn der Zweig feature1vollständig lokal ist, schauen Sie sich das an git rebase.
Jokester
19
Danke, als Git-Anfänger, git rebasescheint mir schwarze Magie zu sein ...
Theomega
13
Wenn es sich bei dem Zweig nur um ein Feature handelt, sollte die Fehlerbehebung dort nicht auftreten (zumindest wenn es sich nicht um einen blockierenden Fehler handelt), da das Ziel dieses Zweigs darin besteht, ein neues Feature anzuzeigen. Der Fehler wird behoben, wenn er mit dem Master zusammengeführt wird, auf dem das Commit mit dem Fix vorhanden ist.
Gipi
21
Wahrscheinlich erwähnenswert für Anfänger, dass in 3. git branch feature1und git checkout feature1kombiniert werden könnte git checkout -b feature1und 4. vollständig aufgit checkout -b hotfix1 master
Naruto Sempai
3
Wären Sie bereit, zurück zu kommen und die akzeptierte Antwort zu ändern, weil die aktuell akzeptierte Antwort schrecklich ist?
Omnifarious

Antworten:

1217

Wie verschmelzen wir den Hauptzweig mit dem Feature-Zweig? Einfach:

git checkout feature1
git merge master

Es macht keinen Sinn, hier eine Schnellvorlaufzusammenführung zu erzwingen, da dies nicht möglich ist. Sie haben sowohl den Feature-Zweig als auch den Master-Zweig festgelegt. Ein schneller Vorlauf ist jetzt unmöglich.

Schauen Sie sich GitFlow an . Es ist ein Verzweigungsmodell für Git, dem man folgen kann, und das haben Sie unbewusst bereits getan. Es ist auch eine Erweiterung von Git, die einige Befehle für die neuen Workflow-Schritte hinzufügt, die Dinge automatisch ausführen, die Sie sonst manuell ausführen müssten.

Was haben Sie in Ihrem Workflow richtig gemacht? Sie müssen mit zwei Zweigen arbeiten. Ihr Feature1-Zweig ist im Grunde der "Entwicklungs" -Zweig im GitFlow-Modell.

Sie haben einen Hotfix-Zweig vom Master erstellt und wieder zusammengeführt. Und jetzt steckst du fest.

Das GitFlow-Modell fordert Sie auf, den Hotfix auch mit dem Entwicklungszweig zusammenzuführen, der in Ihrem Fall "feature1" ist.

Die wirkliche Antwort wäre also:

git checkout feature1
git merge --no-ff hotfix1

Dadurch werden alle Änderungen, die innerhalb des Hotfixes vorgenommen wurden, zum Feature-Zweig hinzugefügt, jedoch nur diese Änderungen. Sie können mit anderen Entwicklungsänderungen in der Verzweigung in Konflikt stehen, sie stehen jedoch nicht in Konflikt mit der Hauptverzweigung, wenn Sie die Feature-Verzweigung schließlich wieder mit der Hauptverzweigung zusammenführen.

Seien Sie beim Umbasieren sehr vorsichtig. Rebase nur, wenn die Änderungen, die Sie vorgenommen haben, lokal in Ihrem Repository geblieben sind, z. B. wenn Sie keine Zweige in ein anderes Repository verschoben haben. Rebasing ist ein großartiges Tool für Sie, um Ihre lokalen Commits in eine nützliche Reihenfolge zu bringen, bevor Sie sie in die Welt hinausschieben.

Sven
quelle
7
Nein. Das Commit zur Behebung des Fehlers wird nur einmal im Hotfix-Zweig angezeigt, obwohl der Zweigname gelöscht wird, sobald er in den Master- und den Entwicklungszweig zusammengeführt wurde. Das Zusammenführungs-Commit zeigt nur die durch das Zusammenführen eingeführten Änderungen an, die wie ein doppeltes Commit aussehen. Aber so funktioniert git: Verzweigen und wieder zusammenführen. Die eigentliche Entwicklungsarbeit findet nur in nicht zusammengeführten Commits statt, und die Zusammenführung wird nur akzeptiert, wenn das Ergebnis funktionierende Software ist.
Sven
42
Dies sollte die akzeptierte Antwort sein. Es funktioniert auch gut mit der Pull-Request-Funktion von GitHub.
Nostalg.io
125
Ich denke, es ist erwähnenswert, dass ein git merge masterTestament von Ihrer lokalen Kopie des Masters zusammengeführt wird. Selbst wenn Sie einen git pullin Ihrem Feature-Zweig erstellt haben, nachdem jemand anderes einen anderen Zweig mit dem Master zusammengeführt hat, müssen Sie git checkout masterdann git pull, dann noch git checkout feature1einmal und DANN git merge master.
Damick
50
@ Damick Oder nur git fetchundgit merge origin/master
Yngvar Kristiansen
20
@damick @ yngvar-kristiansen git pull origin masterwird automatisch orgin/mastermit dem aktuellen Zweig zusammengeführt
L422Y
612

Sie sollten in der Lage sein, Ihren Zweig auf Master neu zu gründen:

git checkout feature1
git rebase master

Verwalten Sie alle auftretenden Konflikte. Wenn Sie zu den Commits mit den Bugfixes kommen (bereits im Master), wird Git sagen, dass es keine Änderungen gab und dass sie möglicherweise bereits angewendet wurden. Anschließend setzen Sie die Rebase fort (während Sie die bereits im Master enthaltenen Commits überspringen) mit

git rebase --skip

Wenn Sie einen git logFeature-Zweig ausführen , wird das Bugfix-Commit nur einmal und im Master-Bereich angezeigt.

Weitere Informationen finden Sie in der Git-Buchdokumentation unter git rebase( https://git-scm.com/docs/git-rebase ), die genau diesen Anwendungsfall abdeckt.

================ Für zusätzlichen Kontext bearbeiten ====================

Diese Antwort wurde speziell für die von @theomega gestellte Frage unter Berücksichtigung seiner besonderen Situation gegeben. Beachten Sie diesen Teil:

Ich möchte [...] Commits in meinem Feature-Zweig verhindern, die keinen Bezug zur Feature-Implementierung haben.

Die Wiederherstellung seiner privaten Niederlassung auf Master ist genau das, was zu diesem Ergebnis führen wird. Im Gegensatz dazu würde das Zusammenführen des Masters in seiner Zweigstelle genau das tun, was er speziell nicht möchte : Hinzufügen eines Commits, das nicht mit der Feature-Implementierung zusammenhängt, an der er über seine Zweigstelle arbeitet.

Um die Benutzer anzusprechen, die den Fragentitel gelesen haben, überspringen Sie den tatsächlichen Inhalt und Kontext der Frage und lesen Sie dann die oberste Antwort nur blind, vorausgesetzt, sie gilt immer für ihren (anderen) Anwendungsfall. Lassen Sie mich Folgendes erläutern:

  • Nur private Zweige neu gründen (dh die nur in Ihrem lokalen Repository vorhanden sind und nicht für andere freigegeben wurden). Das Wiederherstellen gemeinsam genutzter Zweige würde die Kopien anderer Benutzer "beschädigen".
  • Wenn Sie Änderungen von einem Zweig (egal ob es sich um einen Master oder einen anderen Zweig handelt) in einen öffentlichen Zweig integrieren möchten (z. B. Sie haben den Zweig zum Öffnen einer Pull-Anforderung verschoben, aber es gibt jetzt Konflikte mit dem Master, und Sie müssen ihn aktualisieren Um diese Konflikte zu lösen, müssen Sie sie zusammenführen (z. B. mit git merge masterwie in der Antwort von @ Sven).
  • Sie können auch Filialen in Ihre lokalen privaten Filialen einbinden, wenn Sie dies bevorzugen. Beachten Sie jedoch, dass dies zu "ausländischen" Commits in Ihrer Filiale führt.

Wenn Sie mit der Tatsache unzufrieden sind, dass diese Antwort nicht zu Ihrer Situation passt, obwohl sie für @theomega war, ist das Hinzufügen eines Kommentars unten nicht besonders hilfreich: Ich kontrolliere nicht, welche Antwort ausgewählt wird. nur @theomega tut.

David Sulc
quelle
136
Nein, es ist nicht sicher: Wenn Sie die Basis neu erstellen, ändern Sie den Verlauf des Zweigs, was sich auf die Entwickler auswirkt, die den Zweig gezogen haben. inf act, git lässt Sie standardmäßig keinen neu basierten Zweig pushen: Sie müssen das Update -fbeim Drücken erzwingen , um den Zweig mit der neu basierten Version zu überschreiben. Achtung!
David Sulc
17
Wie gehen professionelle Teams mit Git mit diesem Problem um? Achten Sie nur darauf, überlegen Sie genau und machen Sie dann eine -f? Oder ist mein gesamter Workflow fehlerhaft, weil ich einen brauche -f?
Theomega
30
Nun, ich würde die "heilige" Regel wagen, dass Sie den freigegebenen Code nicht neu festlegen (oder auf andere Weise ändern), sondern nur für Ihren lokalen Code. Grundsätzlich sollten Sie Ihre Änderungen auf "Bereinigen" umstellen, bevor Sie sie freigeben. In Ihrem Fall können Sie einen neuen, neu basierten Zweig (mit einem anderen Namen) verschieben und Kollegen bitten, ihre Änderungen auf diesen Zweig zu stützen (dh indem Sie ihren lokalen Zweig wie oben auf den neuen Zweig stützen). Dann löschen Sie feature1aus Github.
David Sulc
19
Die meisten professionellen Teams, an denen ich gearbeitet habe, verwenden fast nie Rebase - sie führen standardmäßig einfach alles zusammen, sodass keine Änderung des Verlaufs erfolgt. Dies ist meine bevorzugte Arbeitsweise. Auf der anderen Seite verwenden einige Teams Rebase, um Commits zu "bereinigen", bevor sie sie pushen (aber niemals nach dem Pushen)
Jonathan Hartley
11
Ja, Sie sollten NIEMALS öffentliche Zweige neu gründen. Die Frage von OP schien sich jedoch mit der Integration neuer Verpflichtungen masterin eine private Niederlassung zu befassen (er erwähnt "seine" lokale Niederlassung). In diesem Fall rebaseist es in Ordnung und entspricht dem von Ihnen erwähnten "Aufräumen".
David Sulc
69

Basierend auf diesem Artikel sollten Sie:

  • Erstellen Sie einen neuen Zweig, der auf der neuen Version des Masters basiert

    git branch -b newmaster

  • Führen Sie Ihren alten Feature-Zweig in einen neuen zusammen

    git checkout newmaster

  • Konflikt im Zweig für neue Funktionen lösen

Die ersten beiden Befehle können zu kombiniert werden git checkout -b newmaster.

Auf diese Weise bleibt Ihr Verlauf klar, da Sie keine Zusammenführungen benötigen. Und Sie müssen nicht so vorsichtig sein, da Sie keine Git-Rebase durchführen müssen.

Zimi
quelle
7
wäre schön, wenn Sie den zugehörigen git-Befehl jedem Punkt folgen lassen. Ansonsten scheint mir dies tatsächlich die sicherere und sauberere Option zu sein.
VirgileD
@zimi Was ist, wenn wir eine entfernte Niederlassung haben? Werden wir den neuen Zweig der Update-Funktionen erneut erstellen? Oder können wir einfach Remote-Upstream einstellen?
Rechnung
@VirgileD Ich habe gerade meine eigene Antwort mit weiteren Details gepostet , einschließlich der zugehörigen Git-Befehle.
JKDEV
29

git merge

Sie können die folgenden Schritte ausführen

1. origin/masterZweig zu featureZweig zusammenführen

# step1: change branch to master, and pull to update all commits
$ git checkout master
$ git pull

# step2: change branch to target, and pull to update commits
$ git checkout feature
$ git pull

# step3: merge master to feature(⚠️ current is feature branch)
$ git merge master

2. featureZweig zu origin/masterZweig zusammenführen

origin/masterist der entfernte Hauptzweig, während masterder lokale Hauptzweig ist

$ git checkout master
$ git pull origin/master

$ git merge feature
$ git push origin/master
xgqfrms
quelle
Fühlt sich an wie Rebase ist hochgespielt! Gute alte Fusion :)!
foreever
27

Zimis Antwort beschreibt diesen Prozess allgemein. Hier sind die Besonderheiten:

  1. Erstellen Sie einen neuen Zweig und wechseln Sie zu ihm. Stellen Sie sicher, dass der neue Zweig auf basiert, masterdamit er die neuesten Hotfixes enthält.

    git checkout master
    git branch feature1_new
    git checkout feature1_new
    
    # Or, combined into one command:
    git checkout -b feature1_new master
    
  2. Führen Sie nach dem Wechsel zum neuen Zweig die Änderungen aus Ihrem vorhandenen Feature-Zweig zusammen. Dadurch werden Ihre Commits hinzugefügt, ohne dass die Hotfix-Commits dupliziert werden.

    git merge feature1
    
  3. Lösen Sie in der neuen Verzweigung alle Konflikte zwischen Ihrer Funktion und der Hauptverzweigung.

Erledigt! Verwenden Sie nun den neuen Zweig, um Ihre Funktion weiterzuentwickeln.

jkdev
quelle
2
Das Problem dabei ist, dass ein Entwickler Zeit damit verschwendet, ständig neue Zweige zu erstellen, wenn diese gegen den Master aktualisiert werden müssen. Wir würden viele, viele Zweige machen, wahrscheinlich dreimal pro Tag während der aktiven Arbeit. Sie sollten Anweisungen schreiben, wie Sie alle lokalen Papierkorbzweige bereinigen und wie Sie sie auch auf der Fernbedienung entfernen können. Wir brauchen auch Ratschläge zur Benennung all dieser Zweige, damit wir nicht verwirrt werden. Ohne dieses Bit wird ein Verzweigungssystem in Chaos verwandelt.
Pauljohn32
4
Du hast recht, das sollte nicht immer gemacht werden. Nur wenn (1) die Änderungen am Master für Ihre Funktion erforderlich sind oder (2) Sie Ihren Zweig mit dem Master zusammenführen und Konflikte auftreten können. Um Unordnung zu vermeiden, können Sie Ihren Zweig nach dem Zusammenführen löschen.
jkdev
11

Hier ist ein Skript, mit dem Sie Ihren Hauptzweig mit Ihrem aktuellen Zweig zusammenführen können.

Das Skript führt Folgendes aus:

  • Wechselt zum Hauptzweig
  • Zieht den Hauptzweig
  • Wechselt zurück zu Ihrer aktuellen Filiale
  • Fügt den Hauptzweig in Ihren aktuellen Zweig ein

Speichern Sie diesen Code als Batch-Datei (.bat) und platzieren Sie das Skript an einer beliebigen Stelle in Ihrem Repository. Klicken Sie dann darauf, um es auszuführen, und Sie sind fertig.

:: This batch file pulls current master and merges into current branch

@echo off

:: Option to use the batch file outside the repo and pass the repo path as an arg
set repoPath=%1
cd %repoPath%

FOR /F "tokens=*" %%g IN ('git rev-parse --abbrev-ref HEAD') do (SET currentBranch=%%g)

echo current branch is %currentBranch%
echo switching to master
git checkout master
echo.
echo pulling origin master
git pull origin master
echo.
echo switching back to %currentBranch%
git checkout %currentBranch%
echo.
echo attemting merge master into %currentBranch%
git merge master
echo.
echo script finished successfully
PAUSE
Aaron M.
quelle
10

Möglicherweise können Sie einen "Cherry-Pick" ausführen, um die genauen Commits, die Sie benötigen, in Ihren Feature-Zweig zu ziehen.

git checkout hotfix1Führen Sie a aus , um in den Zweig hotfix1 zu gelangen. Führen Sie dann a aus git log, um den SHA-1-Hash (große Folge von zufälligen Buchstaben und Zahlen, die ein Commit eindeutig identifizieren) des betreffenden Commits zu erhalten. Kopieren Sie das (oder die ersten 10 oder so Zeichen).

Kehren Sie dann git checkout feature1zu Ihrem Feature-Zweig zurück.

Dann, git cherry-pick <the SHA-1 hash that you just copied>

Dadurch wird dieses Commit und nur dieses Commit in Ihren Feature-Zweig gezogen. Diese Änderung wird in der Branche vorgenommen - Sie haben sie nur "ausgewählt". Nehmen Sie dann die Arbeit wieder auf, bearbeiten Sie sie, legen Sie sie fest, drücken Sie sie usw. nach Herzenslust.

Wenn Sie schließlich eine weitere Zusammenführung von einem Zweig in Ihren Feature-Zweig durchführen (oder umgekehrt), erkennt Git, dass Sie diesen bestimmten Commit bereits zusammengeführt haben , und wissen, dass er nicht erneut erstellt werden muss "überspringen".

Bob Gilmore
quelle
Ich halte das nicht für eine gute Idee. Dann, IMO, wird das Hotfix-Commit wirklich im Verlauf Ihres Feature-Zweigs angezeigt, was Sie im Grunde nicht wollen.
Martin Pecka
1
"Wenn Sie schließlich eine weitere Zusammenführung von einem Zweig in Ihren Feature-Zweig durchführen (oder umgekehrt), erkennt git, dass Sie bereits [...] zusammengeführt haben." - funktioniert das tatsächlich? Ich glaube nicht, dass dies git mergein dieser Art und Weise funktioniert, auf die Sie anscheinend hinweisen („und überspringen Sie es einfach“). Das Mischen von Kirschernte und -mischung kann anscheinend zu Problemen führen; siehe: news.ycombinator.com/item?id=3947950
Guildenstern
0

Ich bin in der Feature-Branche und habe Refactorings durchgeführt. Ich möchte die Masteränderungen jetzt in meinem Feature-Zweig zusammenführen. Ich bin weit zurück. Hinweis Ich möchte die Master-Änderungen nicht auf mein lokales Verzeichnis übertragen, da in meinem Feature-Zweig Module von einem Ort an einen anderen verschoben wurden. Ich fand, dass es nicht funktioniert, nur unten ohne Ziehen aufzutreten. es heißt "Schon auf dem neuesten Stand."

 //below does not get the latest from remote master to my local feature branch without git pull
    git checkout master 
    git fetch 
    git checkout my-feature-branch 
    git merge master

Dies funktioniert unten. Beachten Sie, dass git merge origin / master verwendet wird:

 git checkout master 
    git fetch 
    git checkout my-feature-branch 
    git merge origin/master
Tony
quelle