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.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow