Jak rozdzielić commit na dwa i po co?

Opublikowane przez Tomasz Prasołek w dniu

Pewnie nad tym się teraz zastanawiasz. Przecież commity się łączy w jeden, żeby historia była krótsza! Po co ją wydłużać? Po co w ogóle rozdzielać commit na dwa nowe?

Jest kilka powodów:

  • Chcemy, żeby historia była bardziej czytelna.
  • Chcemy przeorganizować commity (interactive rebase) i powoduje Nam to konflikty.
  • Chcemy trzymać się zasady SRP (Single Responsibility Principle) w commitach, a do jednego wrzuciliśmy za dużo kodu. O tej zasadzie w kontekście gita przeczytałem u Macieja Aniserowicza w poście: 5 Obowiązkowych Sposobów Na Rewelacyjną Pracę Z Gitem (I Nie Tylko). Polecam.
  • Jeśli mamy małe commity łatwiej później cofnąć zmianę przez polecenie git revert.

UWAGA!!! W tym wpisie skupiam się tylko jak rozdzielić commit na dwa. Nie będę dokładnie opisywał jak działa interactive rebase. To jest temat na oddzielny wpis.

Rozdzielanie commita na dwa – krok po kroku

W swoim repozytorium testowym przygotowałem taką sytuację:

Dodałem dwa pliki tekstowe: File1.txt oraz File2.txt. Dodałem do nich jakiś tekst, ale w commicie 18e0ac38 są zmiany zarówno odnoszące się do pliku nr 1, jak i nr 2. Ten commit będę chciał rozdzielić na dwa.

Najpierw robimy interactive rebase:

git rebase -i HEAD~4

Nie będą opisywał co ten tryb potrafi, bo on potrafi dużo i to jest temat na oddzielny wpis. Najważniejsze w tym poleceniu jest ostatnia opcja HEAD~4, oznacza to, że chcemy zmienić ostatnie (najnowsze) 4 commity. Pojawi Nam się okno z naszymi wybranymi commitami:


UWAGA!!! W tym trybie kolejność commitów jest pokazana odwrotnie, najnowszy jest na dole, najstarszy na górze.

Ustawiamy opcję edit dla commita do rozdzielenia. Zmieniamy pick na edit:

Po zapisaniu i wyjściu z tego trybu będziemy w miejscu historii dokładnie po tym commicie. Możesz to sprawdzić przez git lg -5:


Dodatkowo w prawym górnym rogu mamy napisane, że jesteśmy w trakcie operacji REBASE.

Teraz kasujemy ostatni commit:

git reset HEAD~1

Zmiany w nim zrobione zostaną wrzucone do katalogu roboczego. HEAD~1 oznacza, że chcemy usunąć tylko jeden, ostatni (najnowszy) commit.

Po tej operacji widzimy, że mamy zmodyfikowane 2 pliki, nie wrzucone do stage’a:

Najpierw wrzucamy zmiany zrobione w jednym pliku:

git add File1.txt
git commit -m "Fix change in File1.txt"

Następnie dodajemy zmiany z pliku drugiego:

git add File2.txt
git commit -m "Fix change in File2.txt"

Kończymy nasze zmiany poleceniem:

git rebase --continue

I to wszystko. Mamy nadzieję, że nie będziemy mieli żadnego konfliktu 🙂

Można zobaczyć jak teraz wygląda nasza historia:

Podsumowując
git rebase -i HEAD~X # gdzie X to liczba commitów, które chcemy zmienić
# oznacz commit do rozdzielenia przez 'edit' (zamień 'pick' na 'edit'), zapisz i zamknij
git reset HEAD~1
git add [pliki]
git commit -m "Pierwszy commit"
git add [następne pliki]
git commit -m "Pierwszy commit"
git rebase --continue

I tyle 🙂

Mamy 5 commitów, a nie 4. Z commita 18e0ac38 zrobiliśmy dwa nowe: d0d08f5 i 3579430. Jeśli chcemy mieć taką historię to możemy je tak zostawić. Jeśli chcemy mieć krótszą można te nowe commity scalić do commitów z odpowiednimi zmianamy, aby zachować SRP. Wszystko zależy od naszych preferencji.

Kategorie: GitPorady

2 Komentarze

blogprogramisty · 6 września 2018 o 11 h 52 min

Niezłe. Jednak naprawdę musiał bym być mocno zmotywowany aby to zrobić. Z doświadczenia wolałbym chyba zrobić edycje opisu do commita, ze są ta 2 zmiany; )

dotnetomaniak.pl · 5 września 2018 o 10 h 52 min

Jak rozdzielić commit na dwa i po co? – Tomasz Prasołek

Dziękujemy za dodanie artykułu – Trackback z dotnetomaniak.pl

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *