11 Stimmen

Wie verwende ich `git rebase -i` nach `git merge`, ohne alles durcheinander zu bringen?

Ich habe die folgende Situation:

  1. Ich habe einige Commits in meinem lokalen Repository vorgenommen und dann einen großen Merge eines anderen Zweigs (~150 Commits) in den Master. Es hatte eine Menge Konflikte darin.

  2. Jetzt möchte ich einen Commit, den ich vor der Zusammenführung gemacht habe, nach der Zusammenführung verschieben, bevor ich ihn pushe.

Normalerweise würde ich Folgendes verwenden rebase -i für sie.

Leider ist das Standardverhalten den einen Merge-Commit zu brechen, die ich tat, die tatsächlich 150 weitere Commits zu Master in separaten Commits hinzugefügt (ich verstehe, es ist wie, wenn ich Rebase statt Merge verwenden, um mit zu beginnen) - das ist schlechtes Verhalten für mich aus mehreren Gründen.

Ich war sehr froh, als ich die -p Flag für Rebase, das Zusammenführungen beibehält. Leider wurde dadurch dieselbe Zusammenführung erneut angewendet und meine harte Arbeit bei der Konfliktlösung vergessen. Erneut - schlechtes Verhalten!

Gibt es eine Lösung für das, was ich möchte? Verwendung von rebase -i nach der Zusammenführung bestimmte Commits neu anordnen oder bearbeiten, ohne meine Post-Merge-Operationen wiederholen zu müssen?

Danke!

20voto

Cascabel Punkte 449595

Hier ist das, was die rerere-train.sh Skript, das ich in meinem Kommentar erwähnt habe, tut dies - im Wesentlichen führt es die Zusammenführung erneut durch, verwendet Ihre Auflösung und lässt rerere es einfach sehen. Wenn Sie möchten, können Sie dies auch manuell für Ihre einzelne Übertragung tun:

git checkout <parent of merge commit>
git merge <merged commit>         # if this goes cleanly, we're done
git rerere                        # done automatically if rerere.enabled is true
git checkout <merge commit> -- .  # check out the files from the result of the merge
git rerere                        # done automatically if rerere.enabled is true
git reset --hard                  # wipe away the merge

# and you'd want to follow with git checkout <branch> to return to where you were

Sie können aber auch einfach die rerere.enabled auf true, und führen Sie diese Schritte ohne die direkten Aufrufe von git rerere -und Sie wären für die Zukunft gerüstet, da rerere automatisch ausgeführt wird, wenn Sie Konflikte lösen. Dies ist mein Job -Es ist fantastisch.

Wenn Sie das Skript direkt ausführen wollen, sollten Sie es mit Argumenten wie rerere-train.sh ^<commit before the merge> <current branch> . (Die ^commit Notation bedeutet "nicht über diesen Punkt hinaus in die Geschichte gehen", also wird es sich nicht die Mühe machen, dies für alle die Merge-Commits in Ihrem Repo).

Wie auch immer Sie rerere dazu bringen, seine Arbeit zu tun, Sie sollten am Ende die gewünschte Auflösung aufgezeichnet haben. Das heißt, Sie können Ihre rebase -i und wenn Sie auf den Konflikt stoßen, wird rerere die aufgezeichnete Lösung wiederverwenden (REcorded REsolution). Nur als Vorwarnung: Die Dateien bleiben im Index als konfliktbehaftet markiert, so dass Sie sie überprüfen und sich vergewissern können, dass das, was er getan hat, sinnvoll ist. Sobald Sie das getan haben, verwenden Sie git add Sie können sie einchecken, als ob Sie die Konflikte selbst gelöst hätten, und wie gewohnt weitermachen!

En git-rerere Manpage enthält eine sehr schöne, ausführliche Beschreibung der normalen Verwendung von rerere, bei der rerere nie tatsächlich aufgerufen werden muss - das geschieht alles automatisch. Und eine Anmerkung, die nicht hervorgehoben wird: Es basiert alles auf Konflikt-Hunks, so dass es eine Auflösung wiederverwenden kann, selbst wenn der Konflikt an einer völlig anderen Stelle endet, solange es immer noch derselbe textuelle Konflikt ist.

1voto

Robin Green Punkte 30622

Ich habe ein Skript erstellt, das dies ermöglicht hier . Siehe die offene Fragen für bekannte Einschränkungen.

Sie müssen zunächst Folgendes installieren rerere-train.sh auf Ihren PATH. Unter Fedora kann dies mit getan werden:

    install "$(rpm -ql git|grep '/rerere-train.sh$')" ~/bin

1voto

sashoalm Punkte 68243

Ich habe rerere-train.sh von Benutzer @Jefromi's Antwort. Allerdings hatte ich diesen Fehler:

$ ../rerere-train.sh HEAD
C:\Program Files\Git\mingw64/libexec/git-core/git-sh-setup: line 6: .: git-sh-i18n: file not found

Von diesem http://kernel.opensuse.org/cgit/kernel-source/commit/?h=linux-next&id=d52b9f00588bb18d7f7a0e043eea15e6c27ec40c Ich habe das gesehen:

Michal Marek

Die git-sh-setup-Hilfe war offenbar nie für die Verwendung durch Skripten außerhalb von Git verwendet werden. Dies wurde mit git 2.10 deutlich:

Nach Herunterladen einer älteren Version - 2.3.4 portabel - Ich habe es geschafft, die rerere-train.sh Arbeit.

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