Ten artykuł nie jest listą egzotycznych flag do zapamiętania na wszelki wypadek, ale bardziej praktyczny zestaw komend Git, które warto znać, gdy repozytorium przestaje zachowywać się jak spokojna sekwencja pull -> commit -> push.
1. git stash: tymczasowy schowek na zmiany
git stash odkłada niezacommitowane zmiany i przywraca czysty working directory. To przydatna opcja, gdy musisz szybko przełączyć branch, zrobić hotfix albo pobrać zmiany z remote bez mieszania ich z aktualną pracą.
Jeżeli chcesz odłożyć tylko wybrane pliki, podaj ścieżkę na końcu:
stash jest wygodny, ale łatwo zamienić go w mały śmietnik, poneiważ jeśli praca ma potrwać dłużej niż kilka godzin, zwykle lepszy będzie mały commit roboczy na osobnym branchu.
2. git cherry-pick: przenieś konkretny commit
git cherry-pick kopiuje zmianę z wybranego commita na aktualny branch i nie przenosi całej historii brancha, ale tworzy nowy commit z tym samym diffem.
Gdy pojawi się konflikt, Git zatrzyma operację i poczeka na decyzję:
cherry-pick najlepiej działa dla małych, niezależnych commitów: poprawki buga, drobnej zmiany konfiguracyjnej, jednego refaktoru. Jeśli przenosisz w ten sposób połowę brancha, prawdopodobnie lepszy będzie merge albo rebase.
3. git reflog: lokalna czarna skrzynka
Wskaźnik HEAD to wskaźnik pokazujący aktualny commit, na którym pracujesz. Zwykle wskazuje ostatni commit bieżącego brancha. zmienia się przy commitach, resetach, przełączeniach branchy i
rebase. git reflog zapisuje te ruchy lokalnie, dlatego często pozwala
odzyskać commity, które zniknęły z normalnego git log.
Typowy scenariusz: robisz reset --hard, orientujesz się, że to był błąd, a potem szukasz poprzedniego stanu w reflogu.
Reflog pomaga też przy usuniętym branchu:
4. git reset i git revert: dwa różne sposoby cofania
git reset przesuwa aktualny branch na inny commit i w zależności od trybu może zostawić zmiany w staging area, w working directory albo usunąć je z plików roboczych.
Najprostsze rozróżnienie wygląda tak:
| Komenda | Co robi | Kiedy używać |
|---|---|---|
git reset --soft | cofa commit, zostawia zmiany w staging area | gdy chcesz poprawić ostatni commit |
git reset --mixed | cofa commit, zostawia zmiany w working directory | gdy chcesz ponownie ułożyć staging |
git reset --hard | cofa commit i usuwa zmiany z plików roboczych | tylko gdy świadomie porzucasz pracę |
git revert <hash> | dodaje nowy commit cofający wcześniejszą zmianę | gdy commit jest już na remote |
git revert nie przepisuje historii. Dodaje nowy commit, który odwraca konkretną zmianę:
Historię lokalną możesz sprzątać agresywnie, ale już historię współdzieloną traktuj jak kontrakt z innymi osobami pracującymi na repozytorium.
Jeśli chcesz cofnąć zmianę, która trafiła już na branch używany przez zespół albo CI/CD, zacznij od revert. O pracy z automatyzacją po stronie repozytorium więcej piszę w artykule o CI/CD dla Next.js.
5. git bisect: znajdź commit, który zepsuł projekt
git bisect prowadzi Cię przez historię metodą wyszukiwania binarnego. Zamiast ręcznie sprawdzać 40 commitów po kolei, oznaczasz znany dobry i znany zły punkt, a Git sam wybiera kolejne commity do testowania.
Jeśli masz test, który jednoznacznie wykrywa problem, możesz zautomatyzować proces:
Komenda uruchamiana przez git bisect run musi zwracać poprawny kod wyjścia: 0 dla commita dobrego, niezerowy kod dla commita złego oraz 125, jeśli dany commit trzeba pominąć.
6. git rebase -i: uporządkuj lokalną historię
Interaktywny rebase pozwala zmieniać kolejność commitów, poprawiać opisy, łączyć małe commity i usuwać niepotrzebne zmiany przed review.
Git otworzy edytor z listą commitów:
Typowe sprzątanie wygląda tak:
Interaktywny rebase ma największy sens przed wypchnięciem brancha albo przed otwarciem pull requesta. Gdy commit jest już używany przez inne osoby, rebase zaczyna generować koszt synchronizacji.
7. git log: szukaj w historii z precyzją
git log jest bardziej elastyczny niż prosta lista commitów, ponieważ pozwala zawężać historię po autorze, czasie, pliku, opisie albo nawet po fragmencie kodu.
Najbardziej praktyczne warianty:
git log --graph --decorate --oneline --allpokazuje rozjazd branchy w czytelnej formie.git log -- path/to/file.tszawęża historię do jednego pliku.git log -S "nazwaFunkcji"pokazuje commity, w których dany fragment pojawił się albo zniknął.git log -ppokazuje diff każdego commita.
Jeśli debugujesz zmianę zachowania aplikacji, połącz git log -S z testami i narzędziami diagnostycznymi właściwymi dla aplikacji.
8. git diff: zobacz, co naprawdę się zmieniło
git diff pokazuje różnice między working directory, staging area, commitami i branchami. To komenda, którą warto uruchamiać przed commitem częściej niż po fakcie.
Najczęstszy workflow przed commitem:
git diff chroni przed przypadkowym dorzuceniem debug logów, lokalnych zmian konfiguracyjnych albo fragmentu pracy z innego zadania. To szczególnie ważne, gdy pracujesz na dużym branchu i staging robisz partiami.
9. git clean: usuń nieśledzone pliki
git clean usuwa pliki, których Git nie śledzi. To przydatne po eksperymentach, buildach, generowanych plikach albo zmianach zależności, ale jest też jedną z bardziej ryzykownych komend z tej listy.
Różnice są istotne:
| Komenda | Efekt |
|---|---|
git clean -n | pokazuje, co zostałoby usunięte |
git clean -f | usuwa nieśledzone pliki |
git clean -fd | usuwa nieśledzone pliki i katalogi |
git clean -fdx | usuwa także pliki ignorowane przez .gitignore |
git clean -i | uruchamia tryb interaktywny |
Jeśli nie masz pewności, użyj git clean -i. Tryb interaktywny jest wolniejszy, ale daje dodatkową kontrolę nad tym, co faktycznie zniknie.
10. git worktree: kilka branchy bez ciągłego przełączania
git worktree pozwala mieć kilka katalogów roboczych podpiętych do tego samego repozytorium. Każdy katalog może pracować na innym branchu.
To rozwiązuje typowy problem. Wyobraź sobie sytuacje, że jesteś w połowie większej zmiany, a nagle trzeba zrobić review albo hotfix. Bez worktree kończy się to stashowaniem, przełączaniem brancha i późniejszym odtwarzaniem kontekstu. Z worktree otwierasz drugi katalog i pracujesz równolegle.
Ratunkowe scenariusze Git
Poniższe przykłady są skrótem decyzyjnym, ponieważ zakładają, że przed wykonaniem komendy sprawdzasz stan repozytorium przez git status.
Cofnij ostatni lokalny commit, ale zostaw zmiany
Użyj tego, gdy commit jest lokalny i chcesz poprawić treść commita, dodać brakujący plik albo inaczej podzielić zmiany.
Zcommitowałem zmianę na złym branchu
Jeśli commit nie został wypchnięty:
Jeśli commit trafił już na remote, bezpieczniejszy wariant to git revert na złym branchu i git cherry-pick na właściwym.
Chcę zmienić opis ostatniego commita
amend zmienia hash commita. Lokalnie to normalne narzędzie, ale po pushu wymaga ostrożności.
Muszę dodać plik do ostatniego commita
To dobre rozwiązanie, gdy commit nie został jeszcze wypchnięty albo pracujesz na prywatnym branchu.
Wypchnąłem złą zmianę na remote
To najczytelniejsza ścieżka na branchach współdzielonych. Historia pokazuje zarówno pierwotną zmianę, jak i commit cofający.
Chcę cofnąć merge commit
-m 1 oznacza, że jako główną linię historii traktujesz pierwszego rodzica merge commita. Zanim go użyjesz sprawdź merge przez git show HEAD.
Potrzebuję jednego pliku z innego brancha
To czytelniejsza, nowocześniejsza alternatywa dla starszych wariantów opartych o git checkout --.
Chcę sprawdzić, kto zmienił konkretną linię
git blame - nie, nie służy do szukania winnych i najlepiej traktować go jako narzędzie do znalezienia kontekstu: commita, pull requesta, decyzji technicznej albo osoby, którą warto zapytać o szczegóły. Tak, może słowo blame, nie jest najszczęśliwsze w tym kontekście...
Cheat sheet: którą komendę wybrać?
Oto mała i praktyczna ściągawka dla chętnych
| Problem | Komenda |
|---|---|
| Muszę tymczasowo odłożyć zmiany | git stash |
| Chcę przenieść jeden commit | git cherry-pick <hash> |
| Zgubiłem commit po resecie | git reflog |
| Chcę poprawić lokalny ostatni commit | git reset --soft HEAD~1 |
| Chcę cofnąć commit na remote | git revert <hash> |
| Szukam commita z błędem | git bisect |
| Sprzątam lokalną historię | git rebase -i |
| Szukam zmiany w historii | git log -S "fragment" |
| Sprawdzam, co trafi do commita | git diff i git diff --staged |
| Usuwam nieśledzone pliki | git clean -n, potem ostrożnie |
| Pracuję na kilku branchach naraz | git worktree |
