Jak cofnąć commit i odzyskać zmiany w Git: 10 komend ratunkowych

Opublikowano
18 grudnia 2025
Aktualizacja
2 lipca 2026
Czas czytania
8 min czytania

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ą.

Code
# Schowaj zmiany w śledzonych plikach
git stash
 
# Schowaj także nowe, nieśledzone pliki
git stash -u
 
# Schowaj zmiany z opisem
git stash push -m "Work in progress: navbar"
 
# Zobacz listę stashy
git stash list
 
# Przywróć ostatni stash i usuń go ze stosu
git stash pop
 
# Przywróć stash bez usuwania go ze stosu
git stash apply
 
# Przywróć konkretny stash
git stash apply stash@{1}

Jeżeli chcesz odłożyć tylko wybrane pliki, podaj ścieżkę na końcu:

Code
git stash push -m "Tylko formularz kontaktowy" -- src/components/ContactForm.tsx

stash jest wygodny, ale łatwo zamienić go w mały śmietnik. 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.

Code
# Znajdź hash commita na branchu źródłowym
git log --oneline feature-branch
 
# Przełącz się na branch docelowy
git switch main
 
# Przenieś jeden commit
git cherry-pick abc1234
 
# Przenieś kilka commitów
git cherry-pick abc1234 def5678
 
# Nałóż zmianę bez automatycznego commita
git cherry-pick --no-commit abc1234

Gdy pojawi się konflikt, Git zatrzyma operację i poczeka na decyzję:

Code
git cherry-pick abc1234
 
# Rozwiąż konflikty w plikach
git add <resolved-files>
git cherry-pick --continue
 
# Albo wycofaj całą operację
git cherry-pick --abort

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

Code
git reflog
 
# Przykładowy wynik:
# abc1234 HEAD@{0}: commit: Popraw walidację formularza
# def5678 HEAD@{1}: reset: moving to HEAD~3
# 91ab2cd HEAD@{2}: checkout: moving from main to feature/login

Typowy scenariusz: robisz reset --hard, orientujesz się, że to był błąd, a potem szukasz poprzedniego stanu w reflogu.

Code
# Błędna operacja
git reset --hard HEAD~3
 
# Szukasz utraconego commita
git reflog
 
# Bezpieczniej najpierw utworzyć branch ratunkowy
git switch -c recovered-work def5678

Reflog pomaga też przy usuniętym branchu:

Code
git branch -D feature-important
 
git reflog
 
# Po znalezieniu ostatniego commita brancha:
git switch -c feature-important abc1234

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.

Code
git reset --soft HEAD~1
git reset --mixed HEAD~1
git reset --hard HEAD~1

Najprostsze rozróżnienie wygląda tak:

KomendaCo robiKiedy używać
git reset --softcofa commit, zostawia zmiany w staging areagdy chcesz poprawić ostatni commit
git reset --mixedcofa commit, zostawia zmiany w working directorygdy chcesz ponownie ułożyć staging
git reset --hardcofa commit i usuwa zmiany z plików roboczychtylko 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ę:

Code
git revert abc1234

Historię lokalną możesz sprzątać agresywnie, ale już historię współdzieloną traktuj jak kontrakt z innymi osobami pracującymi na repozytorium.

praktyka pracy zespołowej

Jeśli chcesz cofnąć zmianę, która trafiła już na branch używany przez zespół albo , 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.

Code
git bisect start
git bisect bad
git bisect good abc1234
 
# Git przełączy repozytorium na commit w środku zakresu.
# Testujesz aplikację i oznaczasz wynik:
git bisect good
# albo:
git bisect bad
 
# Po znalezieniu winnego commita wracasz do normalnej pracy:
git bisect reset

Jeśli masz test, który jednoznacznie wykrywa problem, możesz zautomatyzować proces:

Code
git bisect start HEAD abc1234
git bisect run npm test

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.

Code
git rebase -i HEAD~3

Git otworzy edytor z listą commitów:

Code
pick abc1234 Add login form
pick def5678 Fix typo
pick ghi9012 Add validation
 
# pick = użyj commit
# reword = zmień opis commita
# squash = połącz z poprzednim i edytuj opis
# fixup = połącz z poprzednim i odrzuć opis
# drop = usuń commit

Typowe sprzątanie wygląda tak:

Code
pick abc1234 Add login form
fixup def5678 Fix typo
squash ghi9012 Add validation

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.

Code
git log --oneline --graph --decorate --all
git log --author="Jan"
git log --since="1 week ago"
git log -- path/to/file.ts
git log --grep="fix validation"
git log -S "validateEmail"
git log -p
git log --stat

Najbardziej praktyczne warianty:

  • git log --graph --decorate --oneline --all pokazuje rozjazd branchy w czytelnej formie.
  • git log -- path/to/file.ts zawęża historię do jednego pliku.
  • git log -S "nazwaFunkcji" pokazuje commity, w których dany fragment pojawił się albo zniknął.
  • git log -p pokazuje 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.

Code
git diff
git diff --staged
git diff main..feature/login
git diff HEAD~1 HEAD
git diff --name-only
git diff -w

Najczęstszy workflow przed commitem:

Code
git status --short
git diff
git diff --staged

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.

Code
git clean -n
git clean -f
git clean -fd
git clean -fdx
git clean -i

Różnice są istotne:

KomendaEfekt
git clean -npokazuje, co zostałoby usunięte
git clean -fusuwa nieśledzone pliki
git clean -fdusuwa nieśledzone pliki i katalogi
git clean -fdxusuwa także pliki ignorowane przez .gitignore
git clean -iuruchamia 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.

Code
git worktree add ../project-hotfix hotfix/payment-error
git worktree list
git worktree remove ../project-hotfix

To rozwiązuje typowy problem. Wyobraź sobie sytuację: 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 to skrót decyzyjny — zakładają, że przed wykonaniem komendy sprawdzasz stan repozytorium przez git status.

Cofnij ostatni lokalny commit, ale zostaw zmiany

Code
git reset --soft HEAD~1

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:

Code
git switch -c correct-branch
git switch previous-branch
git reset --hard HEAD~1

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

Code
git commit --amend -m "Poprawny opis commita"

amend zmienia hash commita. Lokalnie to normalne narzędzie, ale po pushu wymaga ostrożności.

Muszę dodać plik do ostatniego commita

Code
git add forgotten-file.ts
git commit --amend --no-edit

To dobre rozwiązanie, gdy commit nie został jeszcze wypchnięty albo pracujesz na prywatnym branchu.

Wypchnąłem złą zmianę na remote

Code
git revert HEAD
git push

To najczytelniejsza ścieżka na branchach współdzielonych. Historia pokazuje zarówno pierwotną zmianę, jak i commit cofający.

Chcę cofnąć merge commit

Code
git revert -m 1 HEAD

-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

Code
git restore --source other-branch -- path/to/file.ts

To czytelniejsza, nowocześniejsza alternatywa dla starszych wariantów opartych o git checkout --.

Chcę sprawdzić, kto zmienił konkretną linię

Code
git blame path/to/file.ts
git blame -L 10,20 path/to/file.ts

Wbrew nazwie git blame nie służy do szukania winnych — najlepiej traktować go jako narzędzie do znalezienia kontekstu: commita, pull requesta, decyzji technicznej albo osoby, którą warto zapytać o szczegóły.

Cheat sheet: którą komendę wybrać?

Na koniec krótka, praktyczna ściągawka.

ProblemKomenda
Muszę tymczasowo odłożyć zmianygit stash
Chcę przenieść jeden commitgit cherry-pick <hash>
Zgubiłem commit po reseciegit reflog
Chcę poprawić lokalny ostatni commitgit reset --soft HEAD~1
Chcę cofnąć commit na remotegit revert <hash>
Szukam commita z błędemgit bisect
Sprzątam lokalną historięgit rebase -i
Szukam zmiany w historiigit log -S "fragment"
Sprawdzam, co trafi do commitagit diff i git diff --staged
Usuwam nieśledzone plikigit clean -n, potem ostrożnie
Pracuję na kilku branchach narazgit worktree
Połączenie intuicyjności z wydajnością, które zapewnia bezproblemową skalowalność kodu.
React

Często zadawane pytania

Jak cofnąć ostatni commit w Git?

Jeśli commit jest tylko lokalny, użyj git reset --soft HEAD~1, aby zachować zmiany w staging area, albo git reset --mixed HEAD~1, aby zostawić je w working directory. Z kolei, jesli commit trafił już na remote, bezpiecznym rozwiązaniem jest git revert.

Najpierw sprawdź git reflog, znajdź hash tego commita, a potem utwórz branch przez git switch -c recovered-branch <hash>. Musisz pamiętać, że reflog jest lokalny i ma ograniczony czas życia, więc nie czekaj, tylko działaj od razu.

git reset przesuwa wskaźnik brancha i przepisuje historię, dlatego nadaje się głównie do lokalnych commitów. Z kolei git revert tworzy nowy commit cofający zmianę, więc jest właściwym wyborem dla historii współdzielonej z innymi.

git stash przydaje się, gdy masz niezacommitowane zmiany i musisz szybko z jakiegoś powodu przełączyć kontekst. To narzędzie przydaje się w awaryjnych sytuacjach, a nie jest to zamiennik commitów roboczych na osobnym branchu.

git cherry-pick przenosi wybrany commit na aktualny branch, tworząc nowy commit z tą samą zmianą. Używaj go wtedy, gdy masz do czynienia z pojedynczą, niezależną poprawką.

Użyj git bisect: oznacz aktualny commit jako bad, znany działający commit jako good, a Git będzie zawężał zakres metodą wyszukiwania binarnego. Automatyzację tego procesu możesz zrobić przez git bisect run.

O autorze

Maciej Sala

Maciej Sala — Product Manager i Frontend Developer z bogatym doświadczeniem w marketingu internetowym oraz SEO. Na co dzień pracuje z Reactem, Next.js i TypeScriptem, a ostatnio także z Astro i narzędziami do automatyzacji procesów AI. Sprawnie łączy perspektywę produktową z praktycznym podejściem do kodu. Przez kilka lat był związany z branżą gier wideo jako project manager i game designer. Absolwent historii na Uniwersytecie Jagiellońskim oraz studiów podyplomowych z marketingu internetowego na AGH w Krakowie. Po godzinach trenuje na siłowni, maluje figurki i rozwija własne projekty side-projecty.

Pomagam przekładać takie tematy na konkretne wdrożenia w frontendzie, SEO, analityce i procesie produktowym.

Skontaktuj się ze mną

Biblioteka wiedzy

Czytaj dalej

Zobacz więcej wpisów
Agenty AI w CI/CD: code review, testy i SEO bez ręcznego odpalania

Agenty AI w terminalu pomagają pojedynczemu developerowi, ale już agenty AI w CI/CD pomagają całemu zespołowi, ponieważ wtedy każdy PR dostaje ten sam typ automatycznego feedbacku: ryzyka, brakujące testy, potencjalne regresje, problemy SEO albo niespójność z konwencjami projektu.

Maciej Sala

Maciej Sala

Founder StriveLab

Astro i Headless CMS: Integracja Sanity, Storyblok, Strapi

Markdown w plikach projektu działa sprawnie, dopóki treść piszą osoby, które swobodnie pracują w Git. W sytuacji, kiedy klient chce sam zmienić cennik, a redaktor poprawia nagłówek w piątek po południu, repozytorium przestaje być wygodnym CMS-em. Wtedy najlepszy będzie headless CMS, czyli panel dla redakcji i API dla Astro.

Maciej Sala

Maciej Sala

Founder StriveLab

Astro 7: Buildy szybsze nawet o 61%. Przegląd nowości realnie tnących koszty CI/CD

Astro 7 wyszło 22 czerwca 2026 i jeśli miałbym te zmiany opisać jednym słowem, brzmiałoby ono: szybkość . Ale nie ta, którą zobaczy użytkownik w przeglądarce, ponieważ Astro od dawna serwuje statyczny HTML i nie ma tu wiele do poprawy. Tym razem wysiłki developerów poszły w szybkość pracy zespołu: czas builda, pętlę zwrotną w developmencie i skalowanie do projektów liczonych w tysiącach podstron.

Maciej Sala

Maciej Sala

Founder StriveLab