Przypadkowy git push –force – to jeszcze nie koniec świata!

Czy zdarzyło Wam się kiedyś użyć git push --force w sytuacji w której zdecydowanie nie powinniście tego robić? I przez nieuwagę nadpisaliście branch kolegi/koleżanki albo mastera?

Nie jest to takim dużym problemem, jeśli mieliście lokalnie poprzednią wersję tego brancha, który nadpisaliście. Tutaj z pomocą przyjdzie git reflog, który zawiera wszystkie commity jakie wydarzyły się w Waszym lokalnym repozytorium. Dlatego ja dziś nie o tym.

Powiedzmy, że sytuacja jest nieco bardziej skomplikowana, bo nie macie lokalnie wcześniejszej wersji brancha. Na dodatek branch, który nadpisaliście miał już gotowy PR i był gotowy do testów a jedyna osoba, która miała lokalnie wcześniejszą wersję wypoczywa na urlopie, pewna, że jej PR zostanie przetestowany w międczyczasie. Zatem w okolicy nie ma nikogo, kto pomógłby Wam z odtworzeniem tego brancha.

I co teraz, co teraz? Głupio tak będzie autorowi PR później powiedzieć, że niechcący popsuliśmy branch.

Okazuje się, że w takiej sytuacji pomocne może być API Githuba – create reference. Zakładając oczywiście, że Wasze repo jest zlokalizowane właśnie tam. Podejrzewam jednak, że inne systemy takie jak Gitlab czy Bitbucket pozwalają na coś podobnego.

Niech nasz PR wygląda tak:

Użytkownik magoswiat utworzył PR z 4 commitami. 2 z nich “Change 1” i “Change 2” zostały utworzone przez użytkownika programistka, a 2 pozostałe przez użytkownika magoswiat.

Jednak użytkownik programistka lokalnie ma tylko trzy z tych commity:

Więc kiedy przez nieuwagę wyśle git push --force w PR pojawia się informacja:

programistka force-pushed the Feature1 branch from 53f85e2 to 0ac35b1 Compare 18 minutes ago

Tutaj 53f85e2 oznacza commit, którym nadpisaliśmy branch a 0ac35b1 to ostatni commit, który był w poprawnej wersji brancha – przed nadpisaniem. Chociaż nie macie go lokalnie jest on ciągle dostępny na serwerze właśnie z poziomu API.

A oto komenda cURL, która pozwala na stworzenie kopii nadpisanej branchy sprzed jej nadpisania:

curl -u username:token \
  -X POST \
  -H "Accept: application/vnd.github.v3+json" \
  https://api.github.com/repos/some-repo/git/refs \
  -d '{"ref":"refs/heads/the-name-of-the-target-branch","sha":"the-commit-to-be-reverted"}'

gdzie username to nasz login, token to token Githuba (więcej o tworzeniu tokenów do API znajdziecie tutaj). Musicie również uzupełnić dane na temat ścieżki do Waszego repo, brancha, który ma zostać utworzony oraz sam commit. Ważne jest, że hash powinien być podany w pełnej wersji 40 znaków, nie w tej skróconej pokazywanej na stronie z PR.

Wersję 40 znakową możemy odczytać na przykład na stronie, która pojawi się po kliknięciu na odnośnik do commitu w powyższej wiadomości. Wówczas zobaczymy coś takiego i w prawym górnym rogu będziemy mieć pełny hash commitu:

Przykładowo w tym przypadku komenda wygląda tak:

curl -u programistka:token \
  -X POST \
  -H "Accept: application/vnd.github.v3+json" \
  https://api.github.com/repos/programistka/RevertForcePushDemo/git/refs \
  -d '{"ref":"refs/heads/RecoveredBranch","sha":"53f85e2fb8f3cbb77e8e1f299cc2ed0554c52434"}'

Po jej wykonaniu na Githubie pojawi się nowy branch, który zawiera dokładnie te same commity, co PR, który nadpisaliśmy:

I nie trzeba się będzie wstydzić przed kolegą czy koleżanką, że takie z nas gapy;) Pozostaje tylko naprawić teraz nadpisany branch aplikując tam brakujące commity. Można to zrobić korzystając np z cherry-pick.

You might also like