Git
Neueinstellung
Suche…
Syntax
-
git rebase [-i | --interactive] [options] [--exec <cmd>] [--onto <newbase>] [<upstream>] [<branch>]
-
git rebase [-i | --interactive] [options] [--exec <cmd>] [--onto <newbase>] --root [<branch>]
-
git rebase --continue | --skip | --abort | --edit-todo
Parameter
Parameter | Einzelheiten |
---|---|
--fortsetzen | Starten Sie den Umbasierungsprozess neu, nachdem Sie einen Zusammenführungskonflikt gelöst haben. |
--abbrechen | Brechen Sie den Rebase-Vorgang ab und setzen Sie HEAD auf den ursprünglichen Zweig zurück. Wurde beim Start der Rebase-Operation eine Verzweigung bereitgestellt, wird HEAD auf Verzweigung zurückgesetzt. Andernfalls wird HEAD auf die Position zurückgesetzt, an der es sich befand, als der Rebase-Vorgang gestartet wurde. |
--keep-empty | Behalten Sie die Commits, die nichts an ihren Eltern ändern, im Ergebnis. |
--überspringen | Starten Sie den Rebasierungsprozess neu, indem Sie den aktuellen Patch überspringen. |
-m, --merge | Verwenden Sie zum Zusammenfassen Strategien zum Zusammenführen. Wenn die rekursive (Standard-) Zusammenführungsstrategie verwendet wird, kann rebase auf der Upstream-Seite Umbenennungen erkennen. Beachten Sie, dass eine Rebase-Zusammenführung funktioniert, indem jedes Commit aus dem Arbeitszweig oberhalb des Upstream-Zweigs wiedergegeben wird. Aus diesem Grund wird bei einem Verschmelzungskonflikt die als überlieferte Seite die bisher rebasierte Serie, beginnend mit Upstream, und ihre ist der Arbeitszweig. Mit anderen Worten, die Seiten sind vertauscht. |
--stat | Zeigt eine Statistik an, was sich seit der letzten Neubasis geändert hat. Der diffstat wird auch von der Konfigurationsoption rebase.stat gesteuert. |
-x, --exec command | Führen Sie interaktive rebase, Stoppen zwischen jedem Commit und Ausführen - command |
Bemerkungen
Bitte beachten Sie, dass rebase den Repository-Verlauf effektiv umschreibt.
Durch das erneuern von Festschreibungen, die im Remote-Repository vorhanden sind, könnten Repository-Knoten, die von anderen Entwicklern als Basisknoten für ihre Entwicklungen verwendet werden, neu geschrieben werden. Wenn Sie nicht wirklich wissen, was Sie tun, ist es eine bewährte Methode, sich zu vergewissern, bevor Sie Ihre Änderungen übernehmen.
Lokale Niederlassung neu einkaufen
Bei der Neuveränderung werden eine Reihe von Commits auf ein anderes Commit angewendet .
Um eine Verzweigung neu zu rebase
, rebase
Sie die Verzweigung aus und rebase
sie dann auf einer anderen Verzweigung fest.
git checkout topic
git rebase master # rebase current branch onto master branch
Dies würde verursachen:
A---B---C topic
/
D---E---F---G master
Zu etwas werden:
A'--B'--C' topic
/
D---E---F---G master
Diese Operationen können in einem einzigen Befehl kombiniert werden, der die Verzweigung auscheckt und sie sofort wieder herstellt:
git rebase master topic # rebase topic branch onto master branch
Wichtig: Nach der Erneuerung haben die angewendeten Commits einen anderen Hash. Sie sollten Commits nicht zurückweisen, die Sie bereits an einen Remote-Host gesendet haben. Eine Folge davon kann sein, dass Sie nicht in der Lage sind git push
Ihren lokalen Zweig auf einen Remote-Host zu verschieben, wodurch Ihre einzige Option für git push --force
.
Rebase: unsere und ihre, lokal und entfernt
Ein Rebase wechselt die Bedeutung von "uns" und "ihrer":
git checkout topic
git rebase master # rebase topic branch on top of master branch
Was auch immer HEAD darauf zeigt, ist "unser"
Das erste, was eine Rebase tut, ist das Zurücksetzen des HEAD
auf master
; vor Rosinenpickerei aus dem alten Zweig begeht topic
zu einem neuen (Commit jeder im ehemaligen topic
Zweig neu geschrieben wird und wird von einem anderen Hash identifiziert werden).
In Bezug auf von Zusammenführungswerkzeugen verwendete Terminologien (nicht mit lokalem oder Remote-Ref zu verwechseln)
=> local is master ("ours"),
=> remote is topic ("theirs")
Das bedeutet, dass ein Zusammenführungs / Diff-Werkzeug den Upstream-Zweig als local
( master
: der Zweig, auf dem Sie die Basenliste neu definieren) und den Arbeitszweig als remote
( topic
: Die Zweigniederlassung, die neu basiert wird) darstellt.
+-----------------------------------------+
| LOCAL:master | BASE | REMOTE:topic |
+-----------------------------------------+
| MERGED |
+-----------------------------------------+
Inversion dargestellt
Beim Zusammenführen:
c--c--x--x--x(*) <- current branch topic ('*'=HEAD)
\
\
\--y--y--y <- other branch to merge
Wir ändern das aktuelle topic
, also haben wir immer noch das, woran wir gearbeitet haben (und wir verschmelzen aus einem anderen Zweig).
c--c--x--x--x---------o(*) MERGE, still on branch topic
\ ^ /
\ ours /
\ /
--y--y--y--/
^
theirs
Auf einer rebase:
Aber bei einer Rebase wechseln wir die Seiten, denn als Erstes überprüft eine Rebase den Upstream-Zweig, um die aktuellen Commits darüber wiederzugeben!
c--c--x--x--x(*) <- current branch topic ('*'=HEAD)
\
\
\--y--y--y <- upstream branch
Ein git rebase upstream
setzt HEAD
auf den Upstream-Zweig, daher wird der Wechsel von "unserem" und "ihnen" im Vergleich zum vorherigen "aktuellen" Arbeitszweig vorgenommen.
c--c--x--x--x <- former "current" branch, new "theirs"
\
\
\--y--y--y(*) <- set HEAD to this commit, to replay x's on it
^ this will be the new "ours"
|
upstream
Das Fütterungsmaterial wird dann wiederholen ‚ihr‘ verpflichtet auf dem neuen ‚unserem‘ topic
Zweig:
c--c..x..x..x <- old "theirs" commits, now "ghosts", available through "reflogs"
\
\
\--y--y--y--x'--x'--x'(*) <- topic once all x's are replayed,
^ point branch topic to this commit
|
upstream branch
Interaktiver Rebase
Dieses Beispiel soll beschreiben, wie man git rebase
im interaktiven Modus nutzen kann. Es wird erwartet, dass man ein grundlegendes Verständnis davon hat, was git rebase
ist und was es tut.
Interaktiver Rebase wird mit folgendem Befehl initiiert:
git rebase -i
Die Option -i
bezieht sich auf den interaktiven Modus . Mit interaktiver Rebase kann der Benutzer Festschreibungsnachrichten ändern sowie Neuanordnungen, Split- und / oder Squash-Commits (zu einer Kombination kombinieren).
Angenommen, Sie möchten Ihre letzten drei Commits neu anordnen. Dazu können Sie Folgendes ausführen:
git rebase -i HEAD~3
Nachdem Sie die obige Anweisung ausgeführt haben, wird eine Datei in Ihrem Texteditor geöffnet, in der Sie auswählen können, wie Ihre Commits neu festgelegt werden. Ändern Sie in diesem Beispiel einfach die Reihenfolge Ihrer Commits, speichern Sie die Datei und schließen Sie den Editor. Dadurch wird in der von Ihnen angewendeten Reihenfolge eine Neugestaltung eingeleitet. Wenn Sie das git log
überprüfen, werden Ihre Commits in der von Ihnen angegebenen neuen Reihenfolge angezeigt.
Überarbeitung von Commit-Nachrichten
Nun haben Sie entschieden, dass eine der Commit-Nachrichten vage ist, und Sie möchten, dass sie aussagekräftiger ist. Sehen wir uns die letzten drei Commits mit demselben Befehl an.
git rebase -i HEAD~3
Anstatt die Reihenfolge neu zu ordnen, werden die Commits umbasiert. Diesmal ändern wir pick
, den Standard, um ein Commit neu zu reword
an dem Sie die Nachricht ändern möchten.
Wenn Sie den Editor schließen, wird die Rebase initiiert und bei der spezifischen Commit-Nachricht angehalten, die Sie umformulieren wollten. Auf diese Weise können Sie die Festschreibungsnachricht nach Wunsch ändern. Nachdem Sie die Nachricht geändert haben, schließen Sie einfach den Editor, um fortzufahren.
Den Inhalt eines Commits ändern
Neben dem Ändern der Festschreibungsnachricht können Sie auch die durch das Festschreiben vorgenommenen Änderungen anpassen. Ändern Sie dazu einfach die pick
, edit
einen Commit zu edit
. Git stoppt, wenn es bei diesem Commit ankommt, und stellt die ursprünglichen Änderungen des Commits im Staging-Bereich bereit. Sie können diese Änderungen jetzt anpassen, indem Sie sie deaktivieren oder neue Änderungen hinzufügen.
Sobald der Bereitstellungsbereich alle Änderungen enthält, die Sie in diesem Commit wünschen, bestätigen Sie die Änderungen. Die alte Commit-Nachricht wird angezeigt und kann an das neue Commit angepasst werden.
Aufteilen eines einzelnen Commits in mehrere
Angenommen, Sie haben ein Commit vorgenommen, zu einem späteren Zeitpunkt jedoch entschieden, dass dieses Commit in zwei oder mehr Commits aufgeteilt werden kann. Verwenden Sie den gleichen Befehl wie zuvor, ersetzen Sie pick
stattdessen mit edit
und drücken Sie die Eingabetaste.
Nun stoppt git bei dem Commit, das Sie für die Bearbeitung markiert haben, und legt den gesamten Inhalt in den Staging-Bereich. Ab diesem Zeitpunkt können Sie git reset HEAD^
ausführen, um das Commit in Ihrem Arbeitsverzeichnis abzulegen. Anschließend können Sie Ihre Dateien in einer anderen Reihenfolge hinzufügen und festschreiben - letztendlich teilen Sie ein einzelnes Commit in n Commits auf.
Mehrere Commits in einem komprimieren
Angenommen, Sie haben einige Arbeit geleistet und haben mehrere Commits, die Ihrer Meinung nach ein einziges Commit sein könnten. Dafür können Sie git rebase -i HEAD~3
ausführen, wobei 3
durch eine entsprechende Menge an Commits ersetzt wird.
Ersetzen Sie dieses Mal den pick
durch einen squash
. Während der Rebase wird das Commit, das Sie zum Squashing angewiesen haben, zusätzlich zum vorherigen Commit gequetscht. verwandeln sie stattdessen in ein einziges Commit.
Abbruch einer interaktiven Neubasis
Sie haben eine interaktive Datenbank gestartet. In dem Editor, in dem Sie Ihre Commits auswählen, entscheiden Sie, dass etwas nicht funktioniert (beispielsweise fehlt ein Commit oder Sie wählen das falsche Rebase-Ziel), und Sie möchten die Rebase abbrechen.
Löschen Sie dazu einfach alle Commits und Aktionen (dh alle Zeilen, die nicht mit dem #
-Zeichen beginnen), und die Rebase wird abgebrochen!
Der Hilfetext im Editor enthält eigentlich diesen Hinweis:
# Rebase 36d15de..612f2f7 onto 36d15de (3 command(s))
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# Note that empty commits are commented out
Nach einer Rebase drücken
Manchmal müssen Sie den Verlauf mit einer Rebase neu schreiben, aber git push
beschwert sich darüber, weil Sie den Verlauf neu geschrieben haben.
Dies kann mit git push --force
gelöst werden. Berücksichtigen Sie jedoch git push --force-with-lease
, um anzugeben, dass der Push fehlschlagen soll, wenn sich der lokale Remote-Tracking-Zweig von dem Zweig auf der Remote- git push --force-with-lease
unterscheidet, z. B. jemandem sonst nach dem letzten Abruf auf die Fernbedienung gedrückt. Dadurch wird vermieden, dass der letzte Push einer anderen Person versehentlich überschrieben wird.
Hinweis : git push --force
- und sogar --force-with-lease
für diese Angelegenheit - kann ein gefährlicher Befehl sein, da er die Historie des Zweigs neu schreibt. Wenn eine andere Person den Zweig vor dem erzwungenen Schub gezogen hatte, werden Fehler in seinem git pull
oder git fetch
, da der lokale Verlauf und der Remote-Verlauf voneinander abweichen. Dies kann zu unerwarteten Fehlern der Person führen. Bei ausreichender Betrachtung der Wiederherstellungsprotokolle kann die Arbeit des anderen Benutzers wiederhergestellt werden, dies kann jedoch zu viel Zeitverschwendung führen. Wenn Sie einen Zweig mit anderen Mitwirkenden zwingen müssen, versuchen Sie, sich mit ihnen zu koordinieren, damit sie sich nicht mit Fehlern befassen müssen.
Zurück zum ursprünglichen Commit
Seit Git 1.7.12 ist es möglich, bis zum Root-Commit zu rebasieren. Das Root-Commit ist das erste Commit, das jemals in einem Repository ausgeführt wurde, und kann normalerweise nicht bearbeitet werden. Verwenden Sie den folgenden Befehl:
git rebase -i --root
Neuerstellung vor einer Codeüberprüfung
Zusammenfassung
Dieses Ziel besteht darin, alle Ihre verstreuten Commits in aussagekräftigere Commits zu reorganisieren, um Codeüberprüfungen zu vereinfachen. Wenn zu viele Ebenen auf einmal zu viele Änderungen gleichzeitig vorgenommen werden, ist es schwieriger, eine Codeüberprüfung durchzuführen. Wenn Sie Ihre chronologisch erstellten Commits in aktuelle Commits reorganisieren können, ist der Codeüberprüfungsprozess einfacher (und möglicherweise fallen weniger Fehler durch den Codeüberprüfungsprozess).
Dieses übermäßig vereinfachte Beispiel ist nicht die einzige Strategie, mit der git bessere Codeüberprüfungen durchführt. Es ist die Art und Weise, wie ich es mache, und es ist etwas, das andere dazu anregt, darüber nachzudenken, wie man Code-Reviews und Git-Geschichte einfacher / besser macht.
Dies zeigt auch pädagogisch die Kraft der Rebase im Allgemeinen.
In diesem Beispiel wird davon ausgegangen, dass Sie über interaktive Umbasierungen Bescheid wissen.
Vorausgesetzt:
- Sie arbeiten an einem Feature-Zweig von Master
- Ihr Feature verfügt über drei Hauptschichten: Frontend, Backend und DB
- Sie haben eine Menge Commits gemacht, während Sie an einem Funktionszweig gearbeitet haben. Jedes Commit berührt mehrere Ebenen gleichzeitig
- Sie wollen (am Ende) nur drei Commits in Ihrer Branche
- eine, die alle Frontend-Änderungen enthält
- eine, die alle Änderungen am hinteren Ende enthält
- eine, die alle DB-Änderungen enthält
Strategie:
- Wir werden unsere chronologischen Commits in "aktuelle" Commits umwandeln.
- zunächst alle Commits in mehrere, kleinere Commits aufteilen - jeweils nur ein Thema (in unserem Beispiel sind das Front-End, Back-End und DB-Änderungen)
- Dann ordnen Sie unsere aktuellen Commits zusammen und "zerquetschen" Sie sie in einzelne Commits
Beispiel:
$ git log --oneline master..
975430b db adding works: db.sql logic.rb
3702650 trying to allow adding todo items: page.html logic.rb
43b075a first draft: page.html and db.sql
$ git rebase -i master
Dies wird im Texteditor angezeigt:
pick 43b075a first draft: page.html and db.sql
pick 3702650 trying to allow adding todo items: page.html logic.rb
pick 975430b db adding works: db.sql logic.rb
Ändern Sie es zu diesem:
e 43b075a first draft: page.html and db.sql
e 3702650 trying to allow adding todo items: page.html logic.rb
e 975430b db adding works: db.sql logic.rb
Dann wendet git jeweils ein Commit an. Nach jedem Commit wird eine Eingabeaufforderung angezeigt, und Sie können dann Folgendes tun:
Stopped at 43b075a92a952faf999e76c4e4d7fa0f44576579... first draft: page.html and db.sql
You can amend the commit now, with
git commit --amend
Once you are satisfied with your changes, run
git rebase --continue
$ git status
rebase in progress; onto 4975ae9
You are currently editing a commit while rebasing branch 'feature' on '4975ae9'.
(use "git commit --amend" to amend the current commit)
(use "git rebase --continue" once you are satisfied with your changes)
nothing to commit, working directory clean
$ git reset HEAD^ #This 'uncommits' all the changes in this commit.
$ git status -s
M db.sql
M page.html
$ git add db.sql #now we will create the smaller topical commits
$ git commit -m "first draft: db.sql"
$ git add page.html
$ git commit -m "first draft: page.html"
$ git rebase --continue
Dann werden Sie diese Schritte für jedes Commit wiederholen. Am Ende hast du folgendes:
$ git log --oneline
0309336 db adding works: logic.rb
06f81c9 db adding works: db.sql
3264de2 adding todo items: page.html
675a02b adding todo items: logic.rb
272c674 first draft: page.html
08c275d first draft: db.sql
Jetzt führen wir rebase noch einmal aus, um neu zu ordnen und zu squash:
$ git rebase -i master
Dies wird im Texteditor angezeigt:
pick 08c275d first draft: db.sql
pick 272c674 first draft: page.html
pick 675a02b adding todo items: logic.rb
pick 3264de2 adding todo items: page.html
pick 06f81c9 db adding works: db.sql
pick 0309336 db adding works: logic.rb
Ändern Sie es zu diesem:
pick 08c275d first draft: db.sql
s 06f81c9 db adding works: db.sql
pick 675a02b adding todo items: logic.rb
s 0309336 db adding works: logic.rb
pick 272c674 first draft: page.html
s 3264de2 adding todo items: page.html
HINWEIS: Stellen Sie sicher, dass Sie git rebase anweisen, die kleineren aktuellen Commits in der Reihenfolge anzuwenden, in der sie chronologisch festgelegt wurden . Andernfalls haben Sie möglicherweise falsche, unnötige Zusammenführungskonflikte, mit denen Sie fertig werden müssen.
Wenn diese interaktive Rebase alle gesagt und getan ist, erhalten Sie Folgendes:
$ git log --oneline master..
74bdd5f adding todos: GUI layer
e8d8f7e adding todos: business logic layer
121c578 adding todos: DB layer
Rekapitulieren
Sie haben jetzt Ihre chronologischen Commits in aktuelle Commits umgewandelt. Im wirklichen Leben müssen Sie dies möglicherweise nicht jedes Mal tun, aber wenn Sie dies wollen oder müssen, können Sie dies jetzt tun. Außerdem haben Sie hoffentlich mehr über Git Rebase erfahren.
Richten Sie git-pull ein, um automatisch eine Rebase statt einer Zusammenführung durchzuführen
Wenn Ihr Team einen Rebase-basierten Workflow verfolgt, kann es von Vorteil sein, git so einzustellen, dass jeder neu erstellte Zweig während eines git pull
Vorgangs eine Rebase-Operation anstelle einer Merge-Operation ausführt.
Fügen Sie Ihrer .gitconfig
oder .gitconfig
.git/config
Folgendes hinzu, um jeden neuen Zweig so einzurichten, dass er automatisch neu erstellt wird:
[branch]
autosetuprebase = always
Befehlszeile: git config [--global] branch.autosetuprebase always
Alternativ können Sie den Befehl git pull
--rebase
, dass er sich immer so verhält, als ob die Option --rebase
wurde:
[pull]
rebase = true
Befehlszeile: git config [--global] pull.rebase true
Testen aller Commits während der Rebase
Bevor Sie eine Pull-Anforderung erstellen, sollten Sie sicherstellen, dass das Kompilieren erfolgreich ist und die Tests für jedes Commit in der Verzweigung bestanden werden. Dies kann automatisch mit dem Parameter -x
.
Zum Beispiel:
git rebase -i -x make
führt die interaktive Rebase durch und stoppt nach jedem Commit, um make
auszuführen. Falls make
fehlschlägt, gibt git an, um Ihnen die Möglichkeit zu geben, die Probleme zu korrigieren und das Commit zu ändern, bevor Sie mit der nächsten fortfahren.
Autostash konfigurieren
Autostash ist eine sehr nützliche Konfigurationsoption, wenn Sie rebase für lokale Änderungen verwenden. Oft müssen Sie Commits aus dem Upstream-Zweig einbringen, sind aber noch nicht dazu bereit.
Git lässt jedoch nicht zu, dass eine Rebase gestartet wird, wenn das Arbeitsverzeichnis nicht sauber ist. Autostash zur Rettung:
git config --global rebase.autostash # one time configuration
git rebase @{u} # example rebase on upstream branch
Der Autostash wird angewendet, sobald die Erneuerung abgeschlossen ist. Es spielt keine Rolle, ob die Basis erfolgreich abgeschlossen wurde oder ob sie abgebrochen wird. In beiden Fällen wird der Autostash angewendet. Wenn die Erneuerung erfolgreich war und sich das Basis-Commit geändert hat, kann es zu einem Konflikt zwischen dem Autostash und dem neuen Commit kommen. In diesem Fall müssen Sie die Konflikte lösen, bevor Sie sich verpflichten. Dies ist nicht anders als wenn Sie manuell verstaut und dann angewendet hätten, so dass es keinen Nachteil gibt, dies automatisch zu tun.