O kurwa, Git!?!

Git jest trudny: łatwo coś zjebać, a rozgryzienie tego, jak rozwiązać Twój problem jest kurwa niemożliwe. Dokumentacja Gita to taki paradoks kury i jajka: nie wygrzebiesz się z bałaganu 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ć wraz z receptami na wyjście z nich wyłożonymi prostym językiem.

O kurwa, 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 kurwa, 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... nosz kurwa mać, 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 kurwa, 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 kurwa, 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 kurwa, 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 kurwa, 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 kurewsko zaskakujące i nieoczywiste za pierwszym razem, kiedy Ci się to wydarzy!)

O kurwa, 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 pieprzonych komend...

O kurwa, 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 do kurwy nędzy checkout -- brzmi sensownie jako najlepsza metoda wycofania zmian w pliku? :wygraża-pięściami-w-stronę-linusa-torvaldsa:

Jebać to, poddaję się

cd ..
sudo rm -r pieprzony-katalog-z-gitowym-repo
git clone https://jakis.adres.github/pieprzony-katalog-z-gitowym-repo.git
cd pieprzony-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 burdel, ż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 i wulgaryzmów. 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