Blog webdeveloperski Patryk yarpo Jar

git rebase – scalanie wielu commitow do jednego przed mergem

Autor wiadomości Październik 12, 2015

W tym wpisie porusze przydatna funkcje `git rebase`, ktora pozwala scalic ("zesquashowac") kilka commit do jednego, co z kolej pozwoli na czystsza i bardziej przejrzysta historie commitow w repozytorium.

Czego potrzebujesz?

  • podstawowej wiedzy o git
  • (ewentualnie) zainstalowanego gita lokalnie
  • 3 minut

Zalozmy sytuacje, ze pracujesz nad jakims zadaniem i w trakcie pracy kilka razy commitowales swoje zmiany. Nie zawsze byly to commity wartosciowe - niech pierwszy rzucil kamien, kto nigdy nie zacommitowal czegos nieprzetesowanego lub czegos, co na pewno nie dziala jak trzeba [rozroznijmy tu zacommitowac cos takiego, a wrzucic to do mastera/developa ;)].

Niech nasz log wyglada w ten sposob:

bash3-2$ git log
commit c42dcb8fa361f56c4a76ad42d128dee86f0eb5e6
Author: Patryk Jar <e.example@example.com>
Date:   Fri Oct 9 14:02:19 2015 +0100

    commit 4 modifications after code review, refactoring

commit 9cfbe300c02dafe7b83841907e2236389ad97edb
Author: Patryk Jar <e.example@example.com>
Date:   Fri Oct 9 14:01:19 2015 +0100

    commit 3 added logic and tests

commit 2e21624f19d2d165f19a5750af9268d5503ddbc5
Author: Patryk Jar <e.example@example.com>
Date:   Fri Oct 9 12:00:19 2015 +0100

    commit 2 work in progress. Do not merge yet!

commit 83d9f350703b803e77c0219470739104eba73e67
Author: Patryk Jar <e.example@example.com>
Date:   Thu Oct 8 18:00:19 2015 +0100

    commit 1 created module

Zalozmy, ze po tych 4 commitach wszystko jest juz przetestowane, kod zostal oceniony przez innego czlonka zespolu i naniosles jakies poprawki (commit 4). Zdecydowanie jednak "commit 2" i "commit 4" nie wnosza do historii gita za wiele. Co wiecej, dlaczego nie zrobic z tego pojedynczego commita? Po pierwsze za pol roku malo kogo bedzie interesowac, ze w czwartek stworzyles modul, a w piatek skonczyles prace. Co wiecej, ten modul moze nie byc w pelni funkcjonalny - zatem nie mozemy zrobic checkouta tego commita i wdrozyc go na produkcje.

Stad wniosek - wszystkie te commity powinny zostac scalone do jednego. Dzieki temu historia bedzie czystsza, zmiany czytelniejsze, wszystkie commity trafiajace do glownej galezi beda rowniez w pelni wartosciowe (przetestowane, przejrzane, poprawione).

Jak scalic commity w git?

Rozwiazan jest kilka, ja w tym wpisie uzyje `git rebase -i` i opcji `fixup`.

$ git rebase -i HEAD~4

To polecenie powinno wywolac na ekranie liste 4 ostatnich commitow w odwroconej kolejnosci:

pick 83d9f35 commit 1 created module
pick 2e21624 commit 2 work in progress. Do not merge yet!
pick 9cfbe30 commit 3 added logic and tests
pick c42dcb8 commit 4 modifications after code review, refactoring

# Rebase ...
#
# 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
...

Jak widzisz najstarszy jest pierwszy, najnowszy ostatni na liscie.

Aby moc cokolwiek zmienic, musimy zajac sie slowami w lewej kolumnie. Aktualnie wszystkie maja "pick". Z opisu polecen wynika, ze w sumie ta opcja niczego nie zmienia. My skupimy sie na "fixup". Przejdz kursorem do ostatniego na liscie commita `pick c42dcb8` wcisnij na klawiaturze "i" (tryb insert) i zmien "pick" na "fixup". Wlasciwie to samo zrob tez w 3-cim i drugim commicie:

pick 83d9f35 commit 1 created module
fixup 2e21624 commit 2 work in progress. Do not merge yet!
fixup 9cfbe30 commit 3 added logic and tests
fixup c42dcb8 commit 4 modifications after code review, refactoring

Nastepnie wcisnij ESC na klawiaturze, po czym kombinacje, ktora ostatecznie zatwierdzasz wciskajac ENTER:

:wq

Slownie "dwukropek wq" (write quit). Za pierwszym razem bedzie to dla Ciebie dziwne, jesli nie uzywales wczesniej edytora vi. Po kilku probach przywykniesz.

Jesli wszystko pojdzie gladko, to powinienes zobaczyc cos w tym stylu:

$ git rebase -i HEAD~4
Successfully rebased and updated refs/heads/nazwa-galezi.

W tym wpisie zajmuje sie tylko latwa sciezka. Jesli po drodze miales konflikty lub merge'owales inne branche do swojej - calosc moze byc duzo bardziej skomplikowana.

Zmiana wiadomosci commita

Aktualnie nasz git log zawiera tylko jeden commit o wiadomosci:

commit 3 added logic and tests

Troche to bez sensu. Za pomoca `git rebase -i` mozna zmienic i to:

git rebase -i HEAD~1

to wyswietli znany juz ekran z lista commitow, tym razem bedzie to jeden najnowszy:

pick 9cfbe30 commit 3 added logic and tests

Wejdz w tryb edycji (wcisnij "i") i zmien "pick" na "reword". Nastepnie kombinacja, ktora juz niedlugo wejdzie Ci w nawyk: `ESC :wq ENTER`.
Zobaczysz kolejny ekran, na ktorym bedziesz mogl wyedytowac aktualna wiadomosc commita. Postaraj sie, aby ta wiadomosc miala mozliwie wiele sensu. "qfix", "szybka poprawka", "naprawa", "juz ok" sensu nie maja. Pamietaj o globalnym zakresie historii zmian. To, ze Ty pracujsz od miesiaca nad tym samym modulem nie sprawia, ze za rok zrozumiesz o co chodzi, ani ze Stefan siedzacy obok Ciebie bedzie wiedzial, co znaczy "poprawiony konf". Dodatkowo warto zawrzec w tej wiadomosci takze informacje o id z jiry (innego narzedzia do zarzadzania taskami) lub nawet np. link do wiki jesli jest to w jakis sposob istotone.
Oczywiscie po zmianie: `ESC :wq ENTER`.

Push do repozytorium

Wszystko idzie swietnie, ale zapomnielismy, ze juz wczesniej wpushowalismy wszystko do zdalnego repo. Zatem nasza historia galezi i historia z repo wygladaja zupelnie inaczej. Proba wpuszowania tego w tradycyjny sposob skonczy sie kleska:

$git push origin nazwa-galezi

Dostaniesz informacje, ze nie udalo sie tego zrobic (chyba, ze wczesniej nic nie wpushowales i zdalne repo nie wie nic o historii tej galezi). Aby moc teraz spushowac to do repozytorium musimy dodac flage wymuszajaca uznanie naszych zmian `-f`:

$git push origin nazwa-galezi -f

Uwaga: Uznaje sie za _bardzo_ zle wymuszanie przyjecia kodu do strategicznie istotnych galezi, takich jak develop czy master. Jesli robisz to na swojej prywatnej galezi, ktora zostanie usunieta, po skonczonym zadaniu - nie ma sprawy. Jednak na galeziach, na ktorych pracuje aktualnie wiele osob moze byc to przyczyna OLBRZYMICH problemow.

Dzialaj ostroznie i baw sie dobrze 🙂

Warto przeczytac:

Komentarze (0) Trackbacks (0)

Brak komentarzy.


Leave a comment

 

Brak trackbacków.