Nehmen wir an, wir haben die folgende Situation in Git:
Ein erstelltes Repository:
mkdir GitTest2
cd GitTest2
git init
Einige Änderungen im Master werden vorgenommen und übertragen.
echo "On Master" > file
git commit -a -m "Initial commit"
Feature1 wurde von Master abgezweigt und einige Arbeiten sind erledigt:
git branch feature1
git checkout feature1
echo "Feature1" > featureFile
git commit -a -m "Commit für feature1"
In der Zwischenzeit wird ein Fehler im Master-Code entdeckt und ein Hotfix-Zweig eingerichtet
git checkout master
git branch hotfix1
git checkout hotfix1
Der Fehler wird im Hotfix-Zweig behoben und wieder in den Master-Zweig eingebunden (vielleicht nach einer Pull-Anfrage/Code-Review):
echo "Bugfix" > bugfixFile
git commit -a -m "Bugfix Commit"
git checkout master
git merge --no-ff hotfix1
Die Entwicklung von feature1 geht weiter:
git checkout feature1
Angenommen, ich benötige den Hotfix in meinem Funktionszweig, vielleicht weil der Fehler auch dort auftritt. Wie kann ich das erreichen, ohne die Commits in meinem Feature-Branch zu duplizieren?
Ich möchte verhindern, dass ich zwei neue Commits in meinem Feature-Zweig erhalte, die keinen Bezug zur Feature-Implementierung haben. Dies scheint mir besonders wichtig zu sein, wenn ich Pull Requests verwende: Alle diese Commits werden auch in den Pull-Request aufgenommen und müssen überprüft werden, obwohl dies bereits geschehen ist (da der Hotfix bereits im Master ist).
Ich kann ein git merge master --ff-only
nicht durchführen: "fatal: Not possible to fast-forward, aborting.", aber ich bin mir nicht sicher, ob mir das geholfen hat.
Wie führen wir den Master-Zweig mit dem Feature-Zweig zusammen? Ganz einfach:
git checkout feature1
git merge master
Es macht keinen Sinn, hier eine schnelle Zusammenführung zu erzwingen, da dies nicht möglich ist. Sie haben sowohl in den Feature-Zweig als auch in den Master-Zweig übertragen. Ein Fast Forward ist jetzt unmöglich.
Werfen Sie einen Blick auf GitFlow. Es ist ein Verzweigungsmodell für Git, dem man folgen kann, und das Sie unbewusst schon getan haben. Es ist auch eine Erweiterung für Git, die einige Befehle für die neuen Arbeitsschritte hinzufügt, die Dinge automatisch erledigen, die Sie sonst manuell erledigen müssten.
Was haben Sie also in Ihrem Arbeitsablauf richtig gemacht? Sie haben zwei Zweige, mit denen Sie arbeiten können. Ihr feature1-Zweig ist im Grunde der "develop"-Zweig im GitFlow-Modell.
Sie haben einen Hotfix-Zweig aus dem Master-Zweig erstellt und diesen wieder zusammengeführt. Und jetzt stecken Sie fest.
Das GitFlow-Modell fordert Sie auf, den Hotfix auch in den Entwicklungszweig einzubinden, der in Ihrem Fall "feature1" ist.
Die richtige Antwort wäre also:
git checkout feature1
git merge --no-ff hotfix1
Dies fügt alle Änderungen, die innerhalb des Hotfixes gemacht wurden, zum Funktionszweig hinzu, aber nur diese Änderungen. Sie könnten mit anderen Änderungen im Entwicklungszweig kollidieren, aber sie werden nicht mit dem Hauptzweig kollidieren, wenn Sie den Funktionszweig irgendwann wieder mit dem Hauptzweig zusammenführen.
Seien Sie sehr vorsichtig beim Rebasen. Führen Sie ein Rebase nur dann durch, wenn die Änderungen, die Sie vorgenommen haben, lokal in Ihrem Repository bleiben, d.h. Sie haben keine Zweige in ein anderes Repository verschoben. Rebasing ist ein großartiges Werkzeug, um Ihre lokalen Commits in eine sinnvolle Reihenfolge zu bringen, bevor Sie sie in die Welt hinausschieben, aber Rebasing im Nachhinein bringt Git-Anfänger wie Sie durcheinander.
Sie sollten in der Lage sein, Ihren Zweig auf master zu rebasen:
git checkout feature1
git rebase master
Kümmern Sie sich um alle Konflikte, die entstehen. Wenn Sie zu den Commits mit den Bugfixes (die sich bereits in master befinden) kommen, wird Git sagen, dass es keine Änderungen gab und dass sie vielleicht bereits angewendet wurden. Sie fahren dann mit dem Rebase fort (und überspringen dabei die Commits, die bereits in master sind) mit
git rebase --skip
Wenn Sie ein git log
für Ihren Feature-Zweig erstellen, werden Sie sehen, dass der Bugfix-Commit nur einmal erscheint, und zwar im Master-Teil.
Für eine detailliertere Diskussion werfen Sie einen Blick in die Git-Buchdokumentation zu git rebase
(https://git-scm.com/docs/git-rebase), die genau diesen Anwendungsfall behandelt.
================ Bearbeiten für zusätzlichen Kontext ====================
Diese Antwort wurde speziell für die von @theomega gestellte Frage und unter Berücksichtigung seiner besonderen Situation gegeben. Beachten Sie diesen Teil:
Ich möchte [...] Commits auf meinem Feature-Zweig verhindern, die keinen Bezug zur Feature-Implementierung haben.
Seinen privaten Zweig auf master umzuhängen ist genau das, was zu diesem Ergebnis führen wird. Im Gegensatz dazu würde das Zusammenführen von master in seinen Zweig genau das tun, was er speziell nicht will: einen Commit hinzufügen, der keinen Bezug zu der Funktionsimplementierung hat, an der er über seinen Zweig arbeitet.
Um die Benutzer anzusprechen, die den Titel der Frage lesen, den eigentlichen Inhalt und den Kontext der Frage überspringen und dann nur die oberste Antwort blind lesen, in der Annahme, dass sie immer auf ihren (anderen) Anwendungsfall zutrifft, erlauben Sie mir, das näher auszuführen:
git merge master
wie in @Svens Antwort).Schließlich, wenn Sie unglücklich darüber sind, dass diese Antwort nicht die beste Lösung für Ihre Situation ist, obwohl sie es für @theomega war, wird es nicht besonders hilfreich sein, einen Kommentar unten hinzuzufügen: Ich habe keinen Einfluss darauf, welche Antwort ausgewählt wird, das tut nur @theomega.
Sie können vielleicht einen "Cherry-Pick" machen, um die exakten Commits, die Sie brauchen, in Ihren Feature-Zweig zu ziehen.
Führen Sie ein git checkout hotfix1
aus, um auf den hotfix1-Zweig zu gelangen. Führen Sie dann ein git log
aus, um den SHA-1-Hash (eine große Folge von zufälligen Buchstaben und Zahlen, die einen Commit eindeutig identifiziert) des fraglichen Commits zu erhalten. Kopieren Sie diesen (oder die ersten 10 oder so Zeichen).
Führen Sie dann git checkout feature1
aus, um wieder auf Ihren Feature-Zweig zu gelangen.
Dann, git cherry-pick <den SHA-1 Hash, den Sie gerade kopiert haben>
Dadurch wird dieser Commit, und nur dieser Commit, in Ihren Feature-Zweig gezogen. Die Änderung wird in den Zweig übernommen - Sie haben sie gerade "gecherry-pickt". Dann können Sie Ihre Arbeit fortsetzen und nach Herzenslust editieren, committen, pushen, etc.
Wenn Sie irgendwann einen weiteren Merge von einem Zweig in Ihren Feature-Zweig durchführen (oder umgekehrt), erkennt Git, dass Sie diesen Commit bereits eingefügt haben, weiß, dass es ihn nicht noch einmal machen muss, und überspringt ihn einfach.