Szukaj…
Składnia
-
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
Parametry
Parametr | Detale |
---|---|
--kontyntynuj | Uruchom ponownie proces zmiany bazy danych po rozwiązaniu konfliktu scalania. |
--anulować | Przerwij operację rebase i zresetuj HEAD do oryginalnej gałęzi. Jeśli gałąź została udostępniona w momencie rozpoczęcia operacji zmiany bazy, HEAD zostanie zresetowany do gałęzi. W przeciwnym razie HEAD zostanie zresetowany do miejsca, w którym znajdował się w momencie rozpoczęcia operacji zmiany bazy. |
--keep-empty | Zachowaj wyniki, które nie zmieniają niczego od rodziców. |
--pominąć | Uruchom ponownie proces zmiany zasad, pomijając bieżącą poprawkę. |
-m, - zlew | Wykorzystuj strategie scalania, by bazować. Gdy używana jest strategia scalania rekurencyjnego (domyślna), pozwala to bazom danych być świadomym zmian nazw po stronie nadrzędnej. Zauważ, że scalanie rebase polega na odtwarzaniu każdego zatwierdzenia z gałęzi pracującej na gałęzi upstream. Z tego powodu, gdy dochodzi do konfliktu scalania, strona zgłaszana jako nasza to dotychczasowa seria rebasingowa, zaczynająca się od góry, a ich jest działającą gałęzią. Innymi słowy, boki są zamieniane. |
--stat | Pokaż różnicę tego, co zmieniło się w górę od ostatniej bazy. Diffstat jest również kontrolowany przez opcję konfiguracji rebase.stat. |
command -x, --exec | Wykonaj interaktywny rebase, zatrzymując się między każdym zatwierdzeniem a wykonaniem command |
Uwagi
Pamiętaj, że rebase skutecznie przepisuje historię repozytorium.
Przekształcanie zatwierdzeń istniejących w zdalnym repozytorium mogłoby przepisać węzły repozytorium używane przez innych programistów jako węzeł podstawowy dla ich rozwoju. Jeśli naprawdę nie wiesz, co robisz, najlepszą praktyką jest bazowanie przed wprowadzeniem zmian.
Rebasing oddziałów lokalnych
Rebasing stosuje ponownie szereg zatwierdzeń na innym zatwierdzeniu.
Aby rebase
gałęzi, sprawdź gałąź, a następnie rebase
ją na innej gałęzi.
git checkout topic
git rebase master # rebase current branch onto master branch
Spowodowałoby to:
A---B---C topic
/
D---E---F---G master
Zmienić się w:
A'--B'--C' topic
/
D---E---F---G master
Te operacje można połączyć w jedno polecenie, które sprawdza gałąź i natychmiast ją zmienia:
git rebase master topic # rebase topic branch onto master branch
Ważne: Po zmianie bazy zastosowane zatwierdzenia będą miały inny skrót. Nie powinieneś wprowadzać zmian w bazie, które już wypchnąłeś na zdalny host. Konsekwencją może być niezdolność do git push
się z lokalnym rebased oddział do zdalnego hosta, pozostawiając jedyną opcją git push --force
.
Rebase: nasz i ich, lokalny i zdalny
Rebase zmienia znaczenie „nasz” i „ich”:
git checkout topic
git rebase master # rebase topic branch on top of master branch
Cokolwiek wskazuje HEAD, jest „nasze”
Pierwszą rzeczą, którą robi rebase, jest reset HEAD
do master
; przed wybieraniem zatwierdzeń zatwierdza ze starego topic
gałęzi do nowego (każde zatwierdzenie w poprzedniej gałęzi topic
zostanie przepisane i będzie oznaczone innym hashem).
W odniesieniu do terminologii stosowanej przez narzędzia do scalania (nie należy mylić z referencją lokalną lub zdalną )
=> local is master ("ours"),
=> remote is topic ("theirs")
Oznacza to, że narzędzie do scalania / porównywania przedstawi gałąź nadrzędną jako local
( master
: gałąź na której bazujesz), a działającą gałąź jako remote
( topic
: gałąź podlegająca rebasingu)
+-----------------------------------------+
| LOCAL:master | BASE | REMOTE:topic |
+-----------------------------------------+
| MERGED |
+-----------------------------------------+
Inwersja zilustrowana
Podczas łączenia:
c--c--x--x--x(*) <- current branch topic ('*'=HEAD)
\
\
\--y--y--y <- other branch to merge
Nie zmieniamy bieżącego topic
oddziału, więc nadal mamy nad czym pracować (i łączymy się z innego oddziału)
c--c--x--x--x---------o(*) MERGE, still on branch topic
\ ^ /
\ ours /
\ /
--y--y--y--/
^
theirs
Na podstawie:
Ale na rebase zmieniamy strony, ponieważ pierwszą rzeczą, którą robi rebase, jest sprawdzenie gałęzi upstream w celu odtworzenia bieżących commits na nim!
c--c--x--x--x(*) <- current branch topic ('*'=HEAD)
\
\
\--y--y--y <- upstream branch
git rebase upstream
najpierw ustawi HEAD
na odgałęzienie upstream, stąd przełącznik „nasz” i „ich” w porównaniu z poprzednim „bieżącym” działającym działem.
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
Rebase następnie odtworzyć „ich” rewizje na nowym „naszym” topic
oddziału:
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
Interactive Rebase
Ten przykład ma na celu opisanie, w jaki sposób można korzystać z git rebase
w trybie interaktywnym. Oczekuje się, że ktoś ma podstawową wiedzę na temat tego, czym jest git rebase
i co robi.
Interaktywny rebase jest inicjowany za pomocą następującego polecenia:
git rebase -i
Opcja -i
odnosi się do trybu interaktywnego . Korzystając z interaktywnego rebase, użytkownik może zmieniać komunikaty zatwierdzeń, a także zmieniać kolejność, dzielić i / lub zatwierdzać squash (łączenie z jednym).
Powiedz, że chcesz zmienić swoje trzy ostatnie zmiany. Aby to zrobić, możesz uruchomić:
git rebase -i HEAD~3
Po wykonaniu powyższej instrukcji w edytorze tekstu zostanie otwarty plik, w którym będziesz mógł wybrać, w jaki sposób zostaną zatwierdzone zmiany. Na potrzeby tego przykładu wystarczy zmienić kolejność zatwierdzeń, zapisać plik i zamknąć edytor. Spowoduje to zainicjowanie zmiany bazy według złożonego zamówienia. Jeśli sprawdzisz git log
, zobaczysz swoje zatwierdzenia w nowej kolejności, którą określiłeś.
Przewijanie komunikatów zatwierdzania
Teraz zdecydowałeś, że jeden z komunikatów zatwierdzania jest niejasny i chcesz, aby był bardziej opisowy. Przeanalizujmy trzy ostatnie zatwierdzenia za pomocą tego samego polecenia.
git rebase -i HEAD~3
Zamiast przestawiać kolejność, zatwierdzenia zostaną zmienione, tym razem zmienimy pick
, domyślnie, aby reword
zatwierdzenie w miejscu, w którym chcesz zmienić wiadomość.
Po zamknięciu edytora nastąpi ponowne uruchomienie bazy i zatrzyma się na konkretnej wiadomości zatwierdzenia, którą chcesz przeredagować. Umożliwi to zmianę komunikatu zatwierdzenia na dowolne. Po zmianie wiadomości wystarczy zamknąć edytor, aby kontynuować.
Zmiana treści zatwierdzenia
Oprócz zmiany komunikatu zatwierdzenia możesz także dostosować zmiany dokonane przez zatwierdzenie. Aby to zrobić, po prostu zmień pick
aby edit
dla jednego zatwierdzenia. Git zatrzyma się, gdy dotrze do tego zatwierdzenia i zapewni oryginalne zmiany zatwierdzenia w obszarze przeciwności. Możesz teraz dostosować te zmiany, odznaczając je lub dodając nowe.
Gdy tylko obszar pomostowy zawiera wszystkie zmiany, które chcesz w tym zatwierdzeniu, zatwierdz je. Stary komunikat zatwierdzenia zostanie wyświetlony i można go dostosować do nowego zatwierdzenia.
Dzielenie pojedynczego zatwierdzenia na wiele
Powiedzmy, że dokonałeś zatwierdzenia, ale zdecydowałeś później, że zatwierdzenie to można podzielić na dwa lub więcej zatwierdzeń. Korzystając z tego samego polecenia co poprzednio, zamiast tego pick
z edit
i wciśnij enter.
Teraz git zatrzyma się na zatwierdzonym zaznaczeniu do edycji i umieści całą jego zawartość w obszarze testowym. Od tego momentu możesz uruchomić git reset HEAD^
aby umieścić zatwierdzenie w katalogu roboczym. Następnie możesz dodawać i zatwierdzać pliki w innej kolejności - ostatecznie dzieląc pojedyncze zatwierdzenie na n zatwierdzeń.
Zgniatanie wielu zatwierdzeń w jeden
Powiedzmy, że wykonałeś trochę pracy i masz wiele zatwierdzeń, które Twoim zdaniem mogą być pojedynczym zatwierdzeniem. W tym celu możesz wykonać git rebase -i HEAD~3
, zastępując 3
odpowiednią ilością zatwierdzeń.
Tym razem zastąpić pick
z squash
zamiast. Podczas zmiany bazy, zatwierdzenie, które poleciłeś zgnieść, zostanie zmiażdżone na poprzednim zatwierdzeniu; zamieniając je w pojedynczy zatwierdzenie.
Przerwanie interaktywnego wycofania
Uruchomiłeś interaktywną bazę. W edytorze, w którym wybierasz zatwierdzenia, decydujesz, że coś idzie nie tak (na przykład brakuje zatwierdzenia lub wybrałeś niewłaściwe miejsce docelowe bazy) i chcesz przerwać bazę.
Aby to zrobić, po prostu usuń wszystkie zatwierdzenia i akcje (tj. Wszystkie wiersze, które nie zaczynają się od znaku #
), a zmiana bazy zostanie przerwana!
Tekst pomocy w edytorze zawiera następującą wskazówkę:
# 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
Naciskać na rebase
Czasami potrzebujesz przepisać historię z rebase, ale git push
narzeka na to, ponieważ przepisałeś historię.
Można to rozwiązać za pomocą git push --force
, ale rozważ git push --force-with-lease
, wskazując, że chcesz, aby push nie powiódł się, jeśli lokalna gałąź zdalnego śledzenia różni się od gałęzi na pilocie, np. Ktoś w przeciwnym razie wypychany do pilota po ostatnim pobraniu. Zapobiega to przypadkowemu nadpisaniu czyjegoś pchnięcia.
Uwaga : git push --force
- a nawet - --force-with-lease
w tym zakresie - może być niebezpiecznym poleceniem, ponieważ przepisuje historię oddziału. Jeśli inna osoba wyciągnęła gałąź przed wymuszonym wypychaniem, jej / jej git pull
git fetch
lub git fetch
będzie zawierało błędy, ponieważ historia lokalna i historia zdalna są rozbieżne. Może to spowodować nieoczekiwane błędy. Przy wystarczającym spojrzeniu na dzienniki można odzyskać pracę drugiego użytkownika, ale może to prowadzić do dużo straconego czasu. Jeśli musisz wykonać przymusowe wypychanie do oddziału z innymi współpracownikami, spróbuj koordynować z nimi, aby nie musieli radzić sobie z błędami.
Zejdź do początkowego zatwierdzenia
Od wersji Git 1.7.12 można dokonać zmiany bazy do głównego zatwierdzenia. Zatwierdzenie główne jest pierwszym zatwierdzeniem, jakie kiedykolwiek zostało dokonane w repozytorium, i zwykle nie można go edytować. Użyj następującego polecenia:
git rebase -i --root
Rebasing przed przeglądem kodu
streszczenie
Ten cel polega na reorganizacji wszystkich rozproszonych zatwierdzeń na bardziej znaczące zatwierdzenia, aby ułatwić przeglądanie kodu. Jeśli jest zbyt wiele warstw zmian w zbyt wielu plikach jednocześnie, trudniej jest dokonać przeglądu kodu. Jeśli możesz zreorganizować chronologicznie utworzone zatwierdzenia w zatwierdzenia tematyczne, wówczas proces sprawdzania kodu jest łatwiejszy (i prawdopodobnie mniej błędów przechodzi przez proces sprawdzania kodu).
Ten zbyt uproszczony przykład nie jest jedyną strategią używania git do lepszych recenzji kodu. Tak właśnie to robię i jest to coś, co może zainspirować innych do zastanowienia się, jak sprawić, by recenzje kodu i historia gitów były łatwiejsze / lepsze.
To również pedagogicznie pokazuje siłę bazy w ogóle.
W tym przykładzie założono, że wiesz o interaktywnym bazowaniu.
Zarozumiały:
- pracujesz nad gałęzią funkcji nadrzędną
- Twoja funkcja ma trzy główne warstwy: front-end, back-end, DB
- dokonałeś wielu zatwierdzeń podczas pracy nad gałęzią funkcji. Każde zatwierdzenie dotyka wielu warstw jednocześnie
- chcesz (ostatecznie) tylko trzy zatwierdzenia w swoim oddziale
- jeden zawierający wszystkie zmiany interfejsu
- jeden zawierający wszystkie zmiany zaplecza
- jeden zawierający wszystkie zmiany DB
Strategia:
- Zamierzamy zmienić nasze chronologiczne zobowiązania w „aktualne” zobowiązania.
- najpierw podziel wszystkie zatwierdzenia na wiele mniejszych zatwierdzeń - każde zawierające tylko jeden temat na raz (w naszym przykładzie tematami są fronton, back-end, zmiany DB)
- Następnie zmień kolejność naszych aktualnych zatwierdzeń razem i „zmień” je w pojedyncze zatwierdzenia tematyczne
Przykład:
$ 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
Zostanie to pokazane w edytorze tekstu:
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
Zmień to na:
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
Następnie git zastosuje jedno zatwierdzenie na raz. Po każdym zatwierdzeniu pojawi się monit, a następnie możesz wykonać następujące czynności:
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
Następnie powtórzysz te kroki dla każdego zatwierdzenia. W końcu masz to:
$ 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
Teraz ponownie uruchamiamy bazę, aby zmienić kolejność i zgnieść:
$ git rebase -i master
Zostanie to pokazane w edytorze tekstu:
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
Zmień to na:
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
UWAGA: pamiętaj, aby powiedzieć git rebase, aby zastosował / zmiażdżył mniejsze zatwierdzenia miejscowe w kolejności, w jakiej zostały one zatwierdzone chronologicznie . W przeciwnym razie możesz mieć do czynienia z fałszywymi, niepotrzebnymi konfliktami łączenia.
Kiedy to wszystko zostanie powiedziane i zrobione, otrzymasz:
$ git log --oneline master..
74bdd5f adding todos: GUI layer
e8d8f7e adding todos: business logic layer
121c578 adding todos: DB layer
Podsumować
Przekształciłeś teraz swoje chronologiczne zobowiązania w aktualne. W prawdziwym życiu może nie być konieczne robienie tego za każdym razem, ale jeśli chcesz lub musisz to zrobić, teraz możesz. Dodatkowo, mam nadzieję, że nauczyłeś się więcej o git rebase.
Skonfiguruj git-pull, aby automatycznie wykonywał rebase zamiast scalania
Jeśli Twój zespół stosuje przepływ pracy oparty na rebase, może być korzystne skonfigurowanie git, tak aby każda nowo utworzona gałąź wykonała operację rebase zamiast scalania podczas git pull
.
Aby skonfigurować każdy nowy oddział tak, aby automatycznie bazował, dodaj następujące elementy do .gitconfig
lub .git/config
:
[branch]
autosetuprebase = always
Wiersz polecenia: git config [--global] branch.autosetuprebase always
Alternatywnie możesz ustawić polecenie git pull
aby zawsze zachowywało się tak, jakby opcja --rebase
została przekazana:
[pull]
rebase = true
Wiersz polecenia: git config [--global] pull.rebase true
Testowanie wszystkich zatwierdzeń podczas rebase
Przed wysłaniem żądania ściągnięcia warto upewnić się, że kompilacja się powiodła, a testy są przekazywane dla każdego zatwierdzenia w gałęzi. Możemy to zrobić automatycznie, używając parametru -x
.
Na przykład:
git rebase -i -x make
wykona interaktywny rebase i zatrzyma się po każdym zatwierdzeniu do wykonania make
. Jeśli make
nie powiedzie się, git przestanie dawać ci możliwość naprawienia problemów i zmiany zatwierdzenia przed kontynuowaniem wybierania następnego.
Konfigurowanie autostashu
Autostash jest bardzo przydatną opcją konfiguracji, gdy używasz bazy danych do zmian lokalnych. Często może być konieczne wprowadzenie zatwierdzeń z oddziału wyższego szczebla, ale jeszcze nie są gotowe do zatwierdzenia.
Jednak Git nie pozwala na uruchomienie bazy, jeśli katalog roboczy nie jest czysty. Autostash na ratunek:
git config --global rebase.autostash # one time configuration
git rebase @{u} # example rebase on upstream branch
Autostash zostanie zastosowany za każdym razem, gdy zakończy się rebase. Nie ma znaczenia, czy rebase zakończy się pomyślnie, czy też zostanie przerwane. W obu przypadkach zostanie zastosowany autostash. Jeśli ponowne bazowanie zakończyło się powodzeniem, a zatem zatwierdzenie podstawowe uległo zmianie, może wystąpić konflikt między autostashem a nowymi zatwierdzeniami. W takim przypadku będziesz musiał rozwiązać konflikty przed zatwierdzeniem. Nie różni się to tak, jakbyś ręcznie składował, a następnie stosował, więc nie ma żadnej wady robienia tego automatycznie.