2009-04-07 15 views
158

Ich benutze Git seit ungefähr einem Jahr und denke, es ist fantastisch, aber ich habe gerade mit einer zweiten Version des Projekts begonnen und eine neue Niederlassung dafür gestartet. Ich kämpfe ein wenig mit dem besten Weg, um die Dinge zu bewältigen.git - Überspringen bestimmter Commits beim Zusammenführen

Ich habe zwei Zweige namens Master10 (für v1) und Master20 (für v2). Ich habe in der Version 1 auf Branch Master10 Fehlerbehebungen gemacht und neue Sachen von Master20 entwickelt. Immer wenn ich einen Bugfix mache, füge ich ihn in v2 ein, indem ich master20 auschecke und git merge master10 mache. So weit, ist es gut.

Jetzt habe ich jedoch eine Änderung in v1 vorgenommen, die ich in v2 nicht möchte, aber ich möchte weitere Fehlerbehebungen fortsetzen. Wie kann ich Git mitteilen, dass er diesen bestimmten Commit (oder eine Reihe von Commits) überspringen soll, aber dass ich in Zukunft weitere Fehlerbehebungen zusammenführen möchte?

Ich dachte, git rebase könnte was ich brauche aber lesen Sie das Dokument und mein Kopf fast explodiert.

Ich denke, was ich will, ist etwas wie ein "git sync" -Befehl, der git sagt, dass zwei Zweige jetzt synchron sind und in Zukunft die Commits von diesem Sync-Punkt nur zusammenführen.

Jede Hilfe wird geschätzt.

Antwort

234

Wenn Sie die meisten, aber nicht alle Commits auf dem Zweig "maint" zum Beispiel in "master" zusammenführen möchten, können Sie dies tun. Es erfordert etwas Arbeit ---- wie oben erwähnt, ist der übliche Anwendungsfall, alles aus einem Zweig zu verschmelzen --- aber manchmal passiert es, dass Sie eine Version geändert haben, die nicht zurück integriert werden sollte (vielleicht der Code) schon im Master überholt), wie stellst du das dar? Here goes ...

Nehmen wir an, dass maint 5 Änderungen angewendet hat, und einer von diesen (maint ~ 3) soll nicht zurück in den Master zusammengeführt werden, obwohl alle anderen sein sollten. Sie tun dies in drei Phasen: eigentlich alles vor dem einen zusammenführen, sagen git, um maint ~ 3 als verschmolzen zu markieren, auch wenn es nicht ist, und dann den Rest zusammenführen. Die Magie ist:

bash <master>$ git merge maint~4 
bash <master>$ git merge -s ours maint~3 
bash <master>$ git merge maint 

Der erste Befehl verschmilzt alles vor Ihre lästigen maint auf Master begehen. In der Standardnachricht für das Zusammenführungsprotokoll wird erläutert, dass Sie "branch 'maint' (früher Teil)" zusammenführen.

Der zweite Befehl verschmilzt das lästige maint ~ 3 Commit, aber die "-s ours" Option sagt Git eine spezielle "Merge-Strategie" zu verwenden, die in der Tat einfach den Baum, den Sie zusammenführen, ignoriert die Commits, die Sie vollständig zusammenführen. Aber es macht immer noch einen neuen Zusammenführungs-Commit mit HEAD und maint ~ 3 als Eltern, so dass der Revisionsgraph jetzt sagt, dass maint ~ 3 zusammengeführt ist. In der Tat wollen Sie wahrscheinlich auch die Option -m verwenden, um 'merge merge' zu erklären, dass das Mainten ~ 3 Commit tatsächlich ignoriert wird!

Der letzte Befehl führt einfach den Rest von maint (maint ~ 2..maint) in den Master, so dass Sie alle wieder synchronisiert werden.

+0

Ich frage mich allerdings, ob das nicht ein bisschen gefährlich ist: Was soll Mast ~ 3 nicht ignorieren, sondern einfach verschieben? Mit Ihrer Lösung würde jedes nachfolgende git merge maint nicht zurück master ~ 3 zusammenführen. – VonC

+1

Für verschobene Festschreibung, ich würde einen "Unterzweig" erstellen, genau das tun, was Sie beschreiben (einschließlich Git merge -s unsere maint ~ 3), dann alles vom Unterzweig zum Master zusammenführen. Ich glaube, ein zukünftiges "git merge maint" würde diesmal "mast ~ 3" verschmelzen. – VonC

+2

Ich denke, wenn du das Verschmelzen verschieben musst, hast du keine andere Wahl, als es zu überspringen (merge -s uns) und es später anzuwenden der Kirschbaum-Befehl. Sobald das Commit vom Master aus erreichbar ist, kann es nicht mehr zusammengeführt werden. Das doppelte Zusammenführen der gleichen Änderung ist eines der Hauptziele von git. – araqnid

0

Erstellen Sie eine dritte Verzweigung für die gewünschten Änderungen in Master10, aber nicht in Master20. Betrachte Master10 immer als deinen "Master", den stabilsten Zweig von allen. Die Branche, in der alle anderen Zweige ständig mithalten wollen.

+0

Ich denke, das könnte funktionieren, aber ich habe mich selbst in diesen Zustand versetzt, und ein dritter Zweig würde mich wahrscheinlich noch mehr verwirren. :) –

15

Commits enthalten Abstammung. Sie können ein Commit nicht zusammenführen, ohne vorherige Commits zusammenzuführen.

Sie können sie natürlich pflücken. Das ist ein guter Fluss, wenn Sie einen Zweig im Wartungsmodus haben.

+1

Danke, Cherry Pick wird die Arbeit machen. Nicht so schön wie das, was ich mir erhofft habe, aber es wird reichen. –

26

IMHO, das logischste zu tun ist, ist alles zusammenführen, und dann verwenden Sie git zurück (commit_you_dont_want), um es zu entfernen.

Beispiel:

git merge master 
git revert 12345678 

Wenn Sie mehrere haben "ignorieren" begeht, oder möchten Nachricht bearbeiten zurückkehren:

git merge master 
git revert -n 123456 
git revert -n abcdef 
git commit -m "... Except commits 123456 and abcdef" 

dann Ihre Geschichte kann wie folgt aussehen:

| ... Except 123456 and abcdef 
|\ Merge branch 'master' into 'your_branch' 

Wenn Sie Konflikte haben, die NUR diese "to-ignore" Commits beinhalten, können Sie Folgendes verwenden:

git merge master -X ours 

So wird Ihre Version über die andere bestehen. Selbst ohne Fehlermeldungen können Sie diese unerwünschten Commits dennoch "rückgängig machen", da sie möglicherweise andere Änderungen enthalten, die nicht in Konflikt stehen, und Sie wollen sie trotzdem nicht.

Wenn Sie Konflikte haben, die nicht nur die "to-ignore" -Zulassungen betreffen, sollten Sie sie manuell lösen, und Sie müssen sie wahrscheinlich beim Zurücksetzen erneut lösen.

+1

Wenn Sie diese rückgängig gemachten Commits dann später in den betreffenden Zweig zusammenführen wollen, ignoriert Git sie dann? –

+0

@ AnriëtteMyburgh Sie können die Reversionsverpflichtungen rückgängig machen, um sie später in etwas zusammenzuführen, was Sie mit der Strategie "merge -s ours" nicht so leicht machen können. – ikdc

2

Eine Art von Werbung zu meiner project, die im Grunde den von @araqnid beschriebenen Prozess umschließt.

Es ist eine Art Helfer, der Fluss folgende GIT führt:

  • gibt es eine tägliche/wöchentliche Benachrichtigung über verschmilzt Wartungs verzweigt sich in dev/Master-Zweig
  • Zweig Betreuers überprüft den Status anhängig ist und beschließt, ihn/sie selbst, ob alle Commits erforderlich sind und sie entweder blockieren oder Entwickler auffordern, sich selbst zu blockieren. Am Ende wird der Wartungszweig in das Upsteam eingebunden.

Ein Zitat aus der Projektseite:

auf dem Workflow es je möglich Wartung oder kundenspezifische Zweige zusammen mit dem Master-Zweig haben. Diese Verzweigungen werden auch als LTS-Verzweigungen bezeichnet.

Oft gehen die Hotfixes in die Zweige, wo der Fehler gemeldet wurde, und dann wird das Commit wieder in den Master-Zweig zusammengeführt.

Allgemeine Praxis ist es, alle Zweige zu haben, perfekt mit den Master synchronisiert, das heißt Sie eine klare Delta zwischen einem bestimmten Zweig und Master zu verstehen, sehen wollen, ob der Master alle Features und Bugfixes enthält.

Manchmal möchten Sie jedoch keine bestimmten Commits, da sie sind und nicht von anderen Benutzern angezeigt werden. Oder Ihre Master-Zweig divergierte so viel, dass es völlig anderen Ansatz erfordert, um das Problem zu beheben, oder noch besser, das Problem ist nicht mehr vorhanden dort.

Auch im Falle von Cherry-Pick vom Master in den Wartungszweig soll der resultierende Commit im Master blockiert werden.