Git jest trudny: łatwo coś popsuć, a rozgryzienie tego, jak naprawić błędy jest niemożliwe. Dokumentacja Gita to taki paradoks kury i jajka: nie jesteś w stanie znaleźć instrukcji, jak wygrzebać się z bałanu, jeżeli nie wiesz, jak nazywa się to coś, o czym powinieneś wiedzieć, żeby rozwiązać Twój problem.
Oto niektóre złe sytuacje, w które zdarzyło mi się wpakować oraz instrukcje jak z nich wyjść, wyłożone prostym językiem.
O kurczę, coś poszło bardzo nie tak, powiedz że Git ma jakiś magiczny wehikuł czasu!?!
git reflog
# zobaczysz listę wszystkich rzeczy, które
# zrobiłeś(aś) w gicie, we wszystkich branchach!
# każda z nich ma indeks HEAD@{index}
# znajdź tą sprzed momentu, kiedy wszystko się popsuło
git reset HEAD@{index}
# magiczny wehikuł czasu
Możesz tego użyć do odzyskania rzeczy, które przez przypadek usunąłeś(aś), lub do usunięcia czegoś, co próbowałeś(aś) zrobić i zepsuło repozytorium, lub do przywrócenia normalności po nieudanym merge'u, albo po prostu żeby wrócić do momentu, kiedy wszystko było dobrze. Używam komendy reflog
BARDZO CZĘSTO. Czapki z głów dla wielu, wielu, wielu, wielu, wielu ludzi, którzy zasugerowali dodanie jej!
O kurczę, zrobiłem(am) commit i zaraz potem zauważyłem(am), że muszę dodać jedną małą zmianę!
# dokonaj zmiany
git add . # lub dodaj pojedyncze pliki
git commit --amend --no-edit
# teraz Twój ostatni commit zawiera tę zmianę!
# UWAGA: nigdy nie poprawiaj publicznych commitów
Zazwyczaj zdarza mi się tak, gdy zacommituję, uruchomię testy/lintery i... no tak, zapomniałam postawić spację po znaku równości. Możesz także wykonać zmianę jako nowy commit i użyć rebase -i
w celu scalenia obu commitów w jeden, ale ta metoda jest milion razy szybsza.
Uwaga: Nigdy nie poprawiaj commitów, które zostały wypushowane do publicznego/współdzielonego brancha! Poprawiaj tylko te commity, które istnieją jedynie w Twojej kopii lokalnej, no chyba że chcesz popsuć sobie dzień.
O kurczę, muszę zmienić opis mojego ostatniego commitu!
git commit --amend
# postępuj według instrukcji, aby wyedytować treść opisu
Głupie wytyczne formatowania opisów w commitach.
O kurczę, niechcący zacommitowałem(am) do mastera coś, co powinno być w nowym branchu!
# stwórz nowego brancha z aktualnym stanem z mastera
git branch jakas-nazwa-nowego-brancha
# usuń ostatni commit z brancha master
git reset HEAD~ --hard
git checkout jakas-nazwa-nowego-brancha
# Twój commit jest teraz w tym branchu :)
Ważne: to nie zadziała, jeżeli wypushowałeś(aś) już commita do publicznego/współdzielonego brancha, a jeżeli próbowałeś(aś) wcześniej innych sposobów, to prawdopodobnie będziesz musiał(a) wykonać git reset HEAD@{liczba-commitów-wstecz}
zamiast HEAD~
. Smutek, żal i zgrzytanie zębów. Aha, wielu, wielu, wielu ludzi zasugerowało nieznany mi wcześniej genialny sposób jak to zapisać krócej. Wszystkim Wam dziękuję!
O kurczę, niechcący zacommitowałem(am) do nie tego brancha co trzeba!
# wycofaj ostatni commit, ale zachowaj dokonane zmiany
git reset HEAD~ --soft
git stash
# przejdź do prawidłowego brancha
git checkout nazwa-prawidlowego-brancha
git stash pop
git add . # lub dodaj pojedyncze pliki
git commit -m "Twój opis commitu";
# teraz Twoje zmiany są w prawidłowym branchu
Wielu ludzi sugerowało również użycie w tej sytuacji komendy cherry-pick
. Wybierz tę metodę, która wydaje Ci się sensowniejsza!
git checkout nazwa-prawidlowego-brancha
# wybierz ostatni commit do mastera
git cherry-pick master
# usuń go z mastera
git checkout master
git reset HEAD~ --hard
O kurczę, próbowałem(am) zrobić diff, ale nic się nie wyświetliło?!
Jeżeli masz pewność, że dokonałeś(aś) zmian w plikach, a mimo to diff
świeci pustkami, to prawdopodobnie dodałeś(aś) swoje pliki do stagingu i musisz użyć specjalnej flagi.
git diff --staged
¯\_(ツ)_/¯ (tak, wiem że to feature, a nie bug, ale to jest zaskakujące i nieoczywiste za pierwszym razem, kiedy Ci się to wydarzy!)
O kurczę, muszę przywrócić commit dokonany jakieś 5 commitów temu!
# znajdź commit, który chesz przywrócić
git log
# użyj klawiszy ze strzałkami aby poruszać się w górę i w dół po historii
# gdy znajdziesz swój commit, zanotuj jego hash
git revert [zapisany hash]
# git stworzy nowego commita, który przywraca tamten commit
# postępuj zgodnie z instrukcjami, aby uzupełnić opis commitu
# albo po prostu zapisz i zacommituj
Okazuje się, że wcale nie musisz przywracać zmian poprzez ręczne wyszukiwanie i robienie kopiuj-wklej starej zawartości do istniejącego pliku! Jeżeli zacommitowałeś(aś) buga, możesz przywrócić cały commit za jednym zamachem za pomocą revert
.
Możesz także przywrócić pojedynczy plik zamiast całego commitu! Ale oczywiście jak na gita przystało, to zupełnie inny zestaw komend...
O kurczę, muszę wycofać moje zmiany z pliku!
# znajdź hash commitu sprzed momentu, w którym plik został zmieniony
git log
# użyj klawiszy ze strzałkami aby poruszać się w górę i w dół po historii
# gdy znajdziesz swój commit, zanotuj jego hash
git checkout [zanotowany hash] -- sciezka/do/pliku
# stara wersja pliku będzie teraz w Twoim indexie
git commit -m "Wow, nie musisz wycofywać zmian metodą kopiuj-wklej!"
Kiedy wreszcie to ogarnęłam, to było MEGA. MEGA. M-E-G-A. A tak serio, na której planecie checkout --
brzmi sensownie jako najlepsza metoda wycofania zmian w pliku? :wygraża-pięściami-w-stronę-linusa-torvaldsa:
Olać to, poddaję się
cd ..
sudo rm -r glupi-katalog-z-gitowym-repo
git clone https://jakis.adres.github/glupi-katalog-z-gitowym-repo.git
cd glupi-katalog-z-gitowym-repo
Dzięki dla Erica V. za podesłanie. Ewentualne pretensje dotyczące użycia sudo
w tym żarcie proszę kierować do niego.
Ale tak na poważnie, jeżeli w Twoim branchu jest już taki bałagan, że musisz zsynchronizować stan swojego repozytorium ze zdalnym w sposób "zalecany przez Gita", spróbuj tego poniżej. Ale pamiętaj, że te czynności są destrukcyjne i nieodwracalne!
# pobierz najnowszy stan origina
git fetch origin
git checkout master
git reset --hard origin/master
# usuń wszystkie nieśledzone pliki i foldery
git clean -d --force
# powtórz checkout/reset/clean dla każdego skopanego brancha
*Disclaimer: Niniejsza strona nie ma na celu bycia wyczerpującym poradnikiem. Owszem, da się zrobić te same rzeczy z większą dozą teoretycznej czystości czy czegoś tam, ale wypracowałam te kroki metodą prób i błędów, licznych przekleństw i przewracania stolików. A potem wpadłam na szalony pomysł, żeby udostępnić je światu opakowane w zdrową dozę beztroski. Bierzesz albo nie, Twój wybór!
Wielkie dzięki dla wszystkich, którzy przetłumaczyli tę stronę na inne języki, jesteście super! Michael Botha (af) · Khaja Md Sher E Alam (bn) · Eduard Tomek (cs) · Moritz Stückler (de) · Franco Fantini (es) · Hamid Moheb (fa) · Senja Jarva (fi) · Michel (fr) · Alex Tzimas (gr) · Elad Leev (he) · Aryan Sarkar (hi) · Ricky Gultom (id) · fedemcmac (it) · Meiko Hori (ja) · Zhunisali Shanabek (kk) · Gyeongjae Choi (ko) · Rahul Dahal (ne) · Martijn ten Heuvel (nl) · Łukasz Wójcik (pl) · Davi Alexandre (pt_BR) · Catalina Focsa (ro) · Daniil Golubev (ru) · Nemanja Vasić (sr) · Björn Söderqvist (sv) · Kitt Tientanopajai (th) · Taha Paksu (tr) · Andriy Sultanov (ua) · Tao Jiayuan (zh) . Z dodatkową pomocą Allie Jones · Artem Vorotnikov · David Fyffe · Frank Taillandier · Iain Murray · Lucas Larson · Myrzabek Azil
Jeśli chcesz pomóc w dodaniu tłumaczenia na swój język, prześlij PR na GitHub