Interaktywny rebase jest czasami nazywany „Szwajcarskim Scyzorykiem” Git – ponieważ zawiera tak wiele różnych narzędzi, dla tak wielu różnych przypadków użycia! Jest jednak jeden główny, nadrzędny przypadek użycia: czyszczenie lokalnej historii commitów.
Pamiętajmy o słowie „lokalny”: powinien być używany tylko do czyszczenia własnej, lokalnej historii commitów, na przykład przed zintegrowaniem jednej z naszych gałęzi funkcji z gałęzią zespołu. W przeciwieństwie do tego, NIE powinien być używany na historii commitów, która została już wypchnięta i udostępniona na zdalnym repozytorium. Interactive rebase jest jednym z tych narzędzi, które „przepisują” historię Gita – i nie powinieneś tego robić na commitach, które zostały już udostępnione innym.
Po tym małym ostrzeżeniu, spójrzmy na kilka praktycznych przykładów!
Uwaga: dla łatwiejszej wizualizacji scenariuszy i przepływów pracy w tym poście, używam „Tower” Git desktop GUI w niektórych z moich zrzutów ekranu.
Korekta starej wiadomości commit
Czasami zauważasz literówkę w starej wiadomości commit – lub zapomniałeś wspomnieć o czymś w opisie, co jest godne uwagi. Gdybyśmy mówili o ostatnich commitach, moglibyśmy po prostu użyć opcji --amend
polecenia git commit
. Ale dla starszych commitów będziesz musiał użyć interactive rebase, aby zmienić je po fakcie.
Oto przykład błędnego komunikatu commit, który chcemy poprawić:
Zły komunikat commit, który wymaga korekty
Pierwszym krokiem w każdej sesji interactive rebase jest określenie, którą częścią historii commitów chcesz manipulować. Ponownie posłużymy się powyższym przykładem: aby zmienić ten zły commit, musimy rozpocząć sesję od jego rodzica.
Rozpoczęcie naszej interaktywnej sesji rebase
Możemy teraz podać hash tego początkowego commita do polecenia interactive rebase:
$ git rebase -i 0023cddd
Otworzy się teraz okno edytora zawierające listę commitów, które właśnie wybrałeś do manipulacji. I nie bądź zaskoczony, ponieważ są one w odwrotnej kolejności: w interaktywnej sesji rebase, Git ponownie zastosuje stare commity, pozycja po pozycji – co oznacza, że odwrócenie kolejności jest poprawne z punktu widzenia Gita.
Okno edytora z wybranymi commitami
Jeszcze jedna ważna rzecz do zauważenia w tym oknie edytora: nie wykonujesz tutaj rzeczywistych manipulacji! Lub, w tym konkretnym przykładzie, NIE przechodzisz do przodu i nie zmieniasz tutaj komunikatu commit. Zamiast tego, jedynie zaznaczasz commit, który chcesz zmienić, słowem kluczowym action. W naszym przypadku, ponieważ chcemy zmienić komunikat commit’u, zaznaczamy linię słowem „reword”. Jeśli następnie zapiszesz i zamkniesz to okno edytora, otworzy się nowe, zawierające wiadomość ze starego commitu. Teraz nadszedł czas, aby wreszcie wprowadzić zmiany:
Wreszcie możemy wprowadzić nasze zmiany
Po zapisaniu i zamknięciu jeszcze raz, sesja interaktywnego rebase jest zakończona, a nasz stary commit został poprawiony!
Łączenie wielu commitów w jeden
Innym przypadkiem użycia interaktywnego rebase jest sytuacja, gdy chcemy połączyć wiele starych komentarzy w jeden. Chociaż, oczywiście, złota zasada kontroli wersji ma zastosowanie: w większości sytuacji, korzystne jest tworzenie większej ilości mniejszych commitów zamiast kilku dużych. Jednak, jak ze wszystkim, może się okazać, że przesadziliśmy i teraz chcemy połączyć dwa lub więcej starych commitów w jeden.
Aby podać konkretny przykład, powiedzmy, że chcemy połączyć następujące wybrane commity w jeden:
Połączmy wiele commitów w jeden
Tak jak w pierwszym przypadku, zaczynamy od uruchomienia interaktywnej sesji rebase przynajmniej na macierzystym commicie tego, którym chcemy manipulować.
$ git rebase -i 2b504bee
Ponownie, otworzy się okno edytora z listą tej części naszej historii commitów, którą chcemy zmanipulować:
Zaznaczanie linii za pomocą „squash”
Słowo kluczowe akcji, którego zamierzamy tu użyć, nazywa się „squash”. I jest tylko jedna ważna informacja, którą musisz wiedzieć o squashu, aby go użyć: linia, którą oznaczymy słowem kluczowym „squash”, zostanie połączona z linią bezpośrednio powyżej. Dlatego też, jak widać na moim zrzucie ekranu powyżej, oznaczyłem linię #2 słowem „squash”, aby połączyć ją z linią #1.
Możemy teraz zapisać i zamknąć okno edytora i ponownie obserwować, a pojawi się nowe okno: zostaniemy teraz poproszeni o podanie commit message dla nowego commitu, który powstanie po połączeniu tych dwóch starych.
Entering a new message for the new, squashed commit
Po zapisaniu i zamknięciu tego okna edytora, zobaczysz, że został utworzony nowy commit, który zawiera zestawy zmian z obu starych commitów. Voila!
Poprawianie błędu
Innym przypadkiem użycia interaktywnego rebase jest sytuacja, gdy znalazłeś błąd w jednym z wcześniejszych commitów. I nie ma znaczenia, co dokładnie zepsułeś: mogłeś zapomnieć dodać pewną zmianę, powinieneś był usunąć plik lub po prostu wprowadzić literówkę…
Naturalną tendencją w takiej sytuacji jest po prostu utworzenie nowego commitu, który poprawi błąd. Ale z drugiej strony, to spowoduje bałagan w naszej historii commitów: tworzenie oryginalnego commitu, a następnie dodawanie commitów „na wszelki wypadek” tylko po to, aby naprawić błędy… to jest nieuporządkowany sposób pracy. Twoja historia commitów wkrótce stanie się trudna do zrozumienia, ponieważ jest zaśmiecona tymi wszystkimi „szybkimi poprawkami”!
To właśnie tutaj „fixup”, jedno z narzędzi dostarczanych z interaktywnym rebase, jest bardzo przydatne. Fixup bierze ten commit „szybkiej poprawki”, stosuje swoje zmiany do oryginalnego commitu (tym samym poprawiając go), a następnie pozbywa się commitu „band-aid”:
Jak działa „fixup”
Po tym, jak skończymy, wygląda to tak, jakby nigdy nie było problemu z naszym oryginalnym commitem! Przejdźmy więc przez to na praktycznym przykładzie.
Pierwszym krokiem jest zrobienie wszystkiego, co konieczne, aby naprawić problem: może to oznaczać dodanie nowego pliku, wprowadzenie zmian do istniejących, usunięcie przestarzałych plików… musisz „tylko” stworzyć zmiany, które poprawią błąd.
Kolejnym krokiem jest commit tych zmian do repozytorium – ale z małym dodatkiem: podczas tworzenia commitu użyjemy flagi --fixup
i przekażemy Gitowi hash naszego złego commitu:
$ git add corrections.txt$ git commit --fixup 2b504bee
Gdy teraz spojrzysz na historię commitów, zobaczysz, że został utworzony dość zwyczajnie wyglądający commit – prawdopodobnie nie jest to magia i fajerwerki, których byś oczekiwał. Ale jeśli przyjrzysz się bliżej, zobaczysz, że coś się dzieje: nowy commit został automatycznie uzupełniony o „fixup !” i temat naszego złego commitu.
Oryginalny commit i commit naprawiający
Trzecim krokiem jest teraz rozpoczęcie interaktywnej sesji rebase. Ponownie, wybieramy rodzica naszego bad commita jako punkt startowy…
$ git rebase -i 0023cddd --autosquash
… i jako drugą część tajnego sosu, używamy flagi --autosquash
. Opcja ta sprawia, że nie musimy nic robić w otwartym oknie edytora. Przyjrzyj się dokładnie sytuacji:
Nasz commit naprawczy został oznaczony jako „fixup” i posortowany na właściwą pozycję
Zobaczysz, że Git automatycznie zrobił za nas dwie rzeczy:
- Oznaczył nasz commit naprawczy jako „fixup.”
- Zmienił kolejność wierszy tak, aby nasz band-aid commit pojawił się bezpośrednio pod naszym złym commitem. Dzieje się tak, ponieważ fixup działa dokładnie jak squash, łącząc się z linią powyżej.
Innymi słowy: nie pozostaje nam nic innego, jak zapisać i zamknąć okno edytora.
Przyjrzyjrzyjmy się jeszcze raz historii commitów:
Szczęśliwe zakończenie!
Nie tylko nasz pierwotnie zły commit zawiera teraz zmiany z naszego commitu band-aid. Ale na dodatek, brzydki commit band-aid zniknął z historii commitów! Wszystko jest ładne i czyste, tak jakby nigdy nie było problemu!
Odkryj moc interaktywnego rebase
Istnieje wiele przypadków użycia interaktywnego rebase – a większość z nich w dziale „naprawianie błędów”. Aby zapoznać się z innymi przydatnymi rzeczami, które możesz zrobić, polecam darmowy „First Aid Kit for Git”: jest to zbiór krótkich filmów (2-3 minuty na odcinek), które pomogą Ci nauczyć się cofać błędy używając interactive rebase i innych narzędzi Git.
Uwaga redaktora: Musiałem użyć interactive rebase podczas przeglądania tego właśnie postu! Jeden z moich commitów zawierał obraz, który był większy niż 1MB, co jest niezgodne z zasadami projektu strony GitLab. Musiałem się cofnąć i poprawić ten commit, aby zamieścić zamiast niego obrazek o prawidłowym rozmiarze. Dzięki za lekcję, wszechświecie! 😁
Więcej wskazówek i sztuczek Git
- 15 wskazówek Git, które poprawią twój przepływ pracy
- Jak Git Partial Clone pozwala pobrać tylko duży plik, którego potrzebujesz
- Git się zdarza! 6 powszechnych błędów Git i jak je naprawić
O autorze
Tobias Günther jest dyrektorem generalnym Tower, popularnego klienta Git, który pomaga ponad 100 000 programistów na całym świecie być bardziej produktywnym z Git.
Okładka autorstwa David Taljat on Pexels