kann nach Rebase nicht zum Verzweigen drängen

131

Wir verwenden Git und haben eine Hauptniederlassung und Entwicklerzweige. Ich muss eine neue Funktion hinzufügen und dann die Commits für den Master neu festlegen und dann den Master an den CI-Server senden.

Das Problem ist, dass ich bei Konflikten während der Rebase nach Abschluss der Rebase nicht zu meinem Remote-Entwicklerzweig (auf Github) pushen kann, bis ich meinen Remote-Zweig ziehe. Dies führt zu doppelten Commits. Wenn keine Konflikte vorliegen, funktioniert dies wie erwartet.

Frage: Wie synchronisiere ich nach Rebase und Konfliktlösung meine lokalen und Remote-Entwicklerzweige, ohne doppelte Commits zu erstellen?

Konfiguration:

// master branch is the main branch
git checkout master
git checkout -b myNewFeature

// I will work on this at work and at home
git push origin myNewFeature

// work work work on myNewFeature
// master branch has been updated and will conflict with myNewFeature
git pull --rebase origin master

// we have conflicts
// solve conflict
git rebase --continue

//repeat until rebase is complete
git push origin myNewFeature

//ERROR
error: failed to push some refs to '[email protected]:ariklevy/dropLocker.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

// do what git says and pull
git pull origin myNewFeature

git push origin myNewFeature

// Now I have duplicate commits on the remote branch myNewFeature

BEARBEITEN

Es hört sich also so an, als würde dies den Workflow unterbrechen:

Entwickler1, der an myNewFeature arbeitet Entwickler2, der an hisNewFeature arbeitet, verwendet beide den Master als Hauptzweig

developer2 führt myNewFeature in hisNewFeature ein

developer1 wird neu gestartet, Konflikte werden gelöst und anschließend Push-Vorgänge für myNewFeature in den Remote-Zweig erzwungen

Ein paar Tage später führt Entwickler2 myNewFeature wieder in hisNewFeature ein

Wird dies dazu führen, dass die anderen Entwickler Entwickler hassen1?

Matt
quelle
keine Lösung, sondern nur ein Gedanke. wer we? Bist du in einem Team von mehr als nur dir? theySagen Sie (die Leute, die mehr wissen als ich), dass Sie Ihren Code nicht verwenden sollten, wenn Sie ihn teilen rebase. Warum machst du nicht einfach git pullund git merge?
AdamT
Entschuldigung, wir = Entwicklungsteam
Matt
1
Also ja, sollte wahrscheinlich nicht neu basieren, wenn Sie Code freigeben. das kann dazu führen, dass Sie Dinge wie das tun müssen, was unten aufgeführt ist ( forceder Push)
AdamT
Oh, tut mir leid, wenn sie sagen rewriting history, das ist einrebase
AdamT
Wie er sagte, ist es ein eigener Entwicklungszweig, so dass dies kein Problem sein sollte, es sei denn, von jemandem wurde erwartet, dass er das zusammenführt.
Learath2

Antworten:

93

Zunächst müssen Sie und Ihre Mitarbeiter vereinbaren, ob ein Themen- / Entwicklungszweig für die gemeinsame Entwicklung oder nur für Ihren eigenen bestimmt ist. Andere Entwickler wissen, dass sie nicht in meinen Entwicklungszweigen zusammengeführt werden sollen, da sie jederzeit neu basiert werden. Normalerweise sieht der Workflow wie folgt aus:

o-----o-----o-----o-----o-----o       master
 \
   o-----o-----o                      devel0
                \
                  o-----o-----o       devel1

Um mit der Fernbedienung auf dem neuesten Stand zu bleiben, gehe ich wie folgt vor:

 git fetch origin
 git checkout master
 git merge --ff origin/master

Ich mache das aus zwei Gründen. Erstens, weil ich so sehen kann, ob es Remote-Änderungen gibt, ohne von meinem Entwicklungszweig wechseln zu müssen. Zweitens ist es ein Sicherheitsmechanismus, um sicherzustellen, dass ich keine nicht versteckten / festgeschriebenen Änderungen überschreibe. Wenn ich nicht schnell zum Master-Zweig vorspulen kann, bedeutet dies, dass entweder jemand den Remote-Master neu basiert hat (für den er stark ausgepeitscht werden muss) oder ich mich versehentlich zum Master verpflichtet habe und mein Ende bereinigen muss.

Wenn sich dann die Fernbedienung geändert hat und ich schnell auf die neueste Version weitergeleitet habe, werde ich Folgendes neu erstellen:

git checkout devel0
git rebase master
git push -f origin devel0

Andere Entwickler wissen dann, dass sie ihre Entwicklungszweige von meinem neuesten abbauen müssen:

git fetch <remote>
git checkout devel1
git rebase <remote>/devel0

Was zu einer viel saubereren Geschichte führt:

o-----o                                 master
       \
         o-----o-----o                  devel0
                      \
                        o-----o-----o   devel1

Führen Sie Commits nicht nach Belieben hin und her. Es werden nicht nur doppelte Commits erstellt und es ist unmöglich, den Verlauf zu verfolgen, sondern es wird nahezu unmöglich, Regressionen aufgrund einer bestimmten Änderung zu finden (weshalb Sie die Versionskontrolle überhaupt verwenden, oder?). Das Problem, das Sie haben, ist das Ergebnis genau dessen.

Es hört sich auch so an, als würden andere Entwickler Commits für Ihre Entwicklungszweige vornehmen. Können Sie das bestätigen?

Die einzige Zeit zum Zusammenführen ist, wenn Ihr Themenzweig zur Aufnahme bereit ist master.

Als Randnotiz. Wenn sich mehrere Entwickler auf dasselbe Repository festlegen, sollten Sie alle benannte Zweige in Betracht ziehen, um zwischen Entwicklern zu unterscheiden, die Zweige entwickeln. Beispielsweise:

git branch 'my-name/devel-branch'

Alle Themenzweige der Entwickler befinden sich also in ihrer eigenen verschachtelten Gruppe.

Trevor Norris
quelle
1
"Es hört sich auch so an, als würden andere Entwickler Commits für Ihre Entwicklungszweige vornehmen. Können Sie dies bestätigen?" JA, sie sind ...
Matt
Sie haben mich auch auf ein anderes Thema aufmerksam gemacht. Arbeiten zwischen Büro und Zuhause. Ich mache an beiden Stellen Zusammenführungen und am Ende des Tages drücke ich, damit ich dort weitermachen kann, wo ich aufgehört habe. Wenn es dann Zeit ist, sich neu zu gründen, sorgen all diese Commits für Verwirrung. Ich muss meine Zweige als einen Zweig behandeln und neu gründen
Matt
@Matt Ja, diese beiden Probleme werden Ihren Workflow wirklich durcheinander bringen. Zum ersten würde ich den anderen Entwicklern mitteilen, dass nur der Eigentümer eine benannte Verzweigung festlegen kann (z. B. 'matt / devel'). Meiner Meinung nach sollten sich sowieso keine zwei Entwickler auf dieselbe Branche festlegen. Schafft nur Verwirrung. Für später sollten Rebasing und Force Pushing die beiden Standorte auf dem neuesten Stand halten.
Trevor Norris
Gute Antwort. Ich habe eine Nebenfrage, warum benutzt du die --forceFlagge, wenn du das tust git push -f origin devel0?
Nobita
2
@Nobita Wenn ein git pushnicht vorspulen kann (dh der sha-Verlauf stimmt nicht überein), müssen Sie push erzwingen, um den vorherigen Verlauf mit dem neuen Verlauf zu überschreiben, der aus dem generiert wurde git rebase.
Trevor Norris
50

Sie müssen den Push erzwingen, da Sie die Commits weiter nach unten verschoben haben. Git erwartet, dass Sie Commits an der Spitze des Zweigs hinzufügen. git push -f origin myNewFeaturewird Ihr Problem beheben.

Tipp: Oben ist eine legitime Anwendung von Gewalttaten aufgeführt. Schreiben Sie niemals den Verlauf in ein öffentlich zugängliches Repository, sonst werden Sie viele Leute hassen.

Learath2
quelle
1
Ich finde dies der optimalste Weg, um den Workflow aufrechtzuerhalten.
Syed Priom
1
Danke Kumpel. Ich habe diesen Befehl verwendet, um meinen neu basierten lokalen Zweig auf denselben Remote-Zweig zu zwingen.
Wei
11
Verwenden git push --force-with-leaseist viel sicherer als Verwendengit push --force
git push --force-with-lease origin HEAD- Vorausgesetzt, Ihr
Zielzweig
31

Das Wichtigste, was Sie hier beachten sollten, ist, was Pull and Rebase hinter den Kulissen tun.

Ein Pull bewirkt im Grunde zwei Dinge: Abrufen und Zusammenführen. Wenn Sie --rebase einschließen, wird anstelle der Zusammenführung eine Neubasis durchgeführt.

Eine Rebase ist so ziemlich so, als würden Sie alle Ihre lokalen Änderungen seit Ihrer Verzweigung speichern, Ihre Verzweigung schnell zum neuesten Commit auf dem Ziel weiterleiten und Ihre Änderungen in der Reihenfolge oben aufheben.

(Dies erklärt, warum Sie beim Ausführen einer Rebase möglicherweise mehrere Eingabeaufforderungen zur Konfliktlösung erhalten, während Sie bei einer Zusammenführung eine Konfliktlösung erhalten. Sie haben die Möglichkeit, einen Konflikt bei JEDEM Commit zu lösen, der neu basiert, um Ihre Commits anderweitig beizubehalten. )

Sie möchten niemals neu basierte Änderungen auf Remote-Zweige übertragen, da dies den Umschreibungsverlauf darstellt. Natürlich ist es nie ein bisschen stark, da es fast immer Ausnahmen gibt. Der Fall, dass Sie eine Remote-Version Ihres lokalen Repositorys verwalten müssen, um beispielsweise in einer bestimmten Umgebung arbeiten zu können.

Dies erfordert, dass Sie neu basierte Änderungen zeitweise entweder mit Gewalt vorantreiben:

git push -f origin newfeature

In einigen Fällen hat Ihr Administrator möglicherweise die Möglichkeit zum Erzwingen entfernt, sodass Sie Folgendes löschen und neu erstellen müssen:

git push origin :newfeature
git push origin newfeature

In beiden Fällen müssen Sie absolut sicher sein, dass Sie wissen, was Sie tun, wenn jemand anderes in Ihrer Remote-Niederlassung mit Ihnen zusammenarbeitet. Dies kann bedeuten, dass Sie zunächst mit Zusammenführungen zusammenarbeiten und diese in ein besser verwaltbares Festschreibungsformat umwandeln, bevor Sie Ihren Arbeitszweig beherrschen und entfernen.

Denken Sie daran, dass Sie fast immer auf den GC von git zurückgreifen können, indem Sie Folgendes nutzen:

git reflog

Dies ist ein RIESIGER Lebensretter, da Sie in einen stabileren Zustand zurückkehren können, wenn Sie sich in Ihrem gesamten Rebase- / Konfliktmanagement verlieren.

Matthew Sanders
quelle
Die obige Option zum Löschen und Neuerstellen hat bei mir gut funktioniert. Kein Forcen auf meinem Repo erlaubt!
Simon Holmes
2

Sie müssen einen erzwungenen Stoß ausführen, dh git push -f origin myNewFeature

Oh, und Sie sollten verdammt noch mal sicherstellen, dass die Leute nichts auf Ihrem Entwicklungszweig basieren - normalerweise sollten Sie keine Zweige veröffentlichen, in denen Sie den Verlauf überhaupt neu schreiben (oder lieber den einmal veröffentlichten Verlauf nicht neu schreiben). Eine Möglichkeit wäre, einen Zweignamen wie zu verwenden wip/myNewFeatureund dann zu erwähnen, dass wipZweige von Zeit zu Zeit neu gemastert werden, um sie zu beherrschen.

DiebMaster
quelle
Verwenden git push --force-with-leaseist viel sicherer als Verwendengit push --force
@ MrCholo Die Leute werden nicht damit anfangen, bis Git eine kurze Option dafür hinzufügt, wie -ffür einen normalen erzwungenen Push :)
ThiefMaster
ha ja, ich habe es in einem automatisierten Skript verwendet,
2

Die allgemeine Antwort, die bereits gegeben wurde, um neu git push -f origin myNewFeaturegestaltete Änderungen voranzutreiben, ist ein guter Ausgangspunkt. Ich schreibe diese Antwort, um die Bearbeitung darüber anzusprechen, ob dadurch Ihr Workflow unterbrochen wird.

Wenn wir davon ausgehen , dass Sie werden mit gehst git pull --rebase ...(oder einer Variation auf , dass) , gefolgt von einem Kraft-Push an den entfernten Zweig, dann die Sache , dass bricht der Workflow in Ihrem Beispiel ist Developer2 verschmilzt myNewFeaturein hisNewFeature. Es ist sinnvoll, Ihren eigenen Feature-Zweig neu zu gründen, solange niemand an diesem Zweig arbeitet. Daher benötigen Sie Regeln, um das Zweiggebiet abzugrenzen.

Sie können dies umgehen, indem Sie a) eine Regel festlegen, aus der Sie immer nur zusammenführen master, oder b) einen kollektiven developZweig erstellen , auf dem Sie Ihren eigenen myNewFeatureZweig aufbauen , und eine Regel festlegen, aus der Sie immer nur zusammenführen develop. masterwird dann nur für Meilensteine ​​oder Releases reserviert (oder wie auch immer Sie dies einrichten möchten) und developist der Ort, an dem Sie jedes Feature pushen, wenn es bereit ist, in andere Feature-Zweige integriert zu werden.

Ich glaube, dies könnte als vereinfachte Version des Gitflow-Workflows angesehen werden.

cosmicFluke
quelle
1

Ich stimme MrCholo zu , und vielleicht könnte Trevor Norris erwägen, seine gute Antwort zu aktualisieren, um sie zu ersetzen

git push -f origin devel0

mit

git push --force-with-lease origin devel0
Sylvain Lesage
quelle