git push –force és hogyan kezeljük

Voltál már olyan helyzetben, amikor egy rossz git parancs pusztítást végzett a projekted repóján? Az emberek hibáznak, és néha ezek a hibák órákba kerülhetnek a csapatod idejéből. Ebben a bemutatóban megmutatjuk, hogyan lehet gyorsan helyreállni egy szerencsétlen git push --forceből.

Ne legyünk túlságosan magabiztosak. Előbb vagy utóbb ez is meg fog történni. Miközben több távoli ággal dolgozol ugyanabban a git-repositoryban, előbb-utóbb git push --force a master-be (vagy egy másik fontos ágba, amellyel soha nem szabad szórakozni).

Ez megtörténhet például a Deis vagy a Heroku segítségével történő telepítéskor, amelyek külön git távoli ágakat használnak az alkalmazás építéséhez és telepítéséhez. Egy hosszú munkanap után hihetetlenül könnyű a szokásos git push --force deis master helyett git push --force-t végrehajtani.

Oops! Egy szempillantás alatt a csapattársaid elvesztették az összes legutóbbi munkájukat. Ideje szembenézni a dühükkel.

Mindamellett, ahogy egy kiváló útmutató mondja: NE PÁNIKOLJ! A jó dolog az, hogy git-et használsz, és ez azt jelenti, hogy mindent ki lehet javítani.

A legjobb esetben: valaki más, aki ugyanazon a kódon dolgozik, épp azelőtt húzta ki a master egy friss verzióját, mielőtt te elrontottad volna. Ekkor csak annyit kell tenned, hogy belépsz a csapatod csevegésébe, és megkéred ezt a személyt, hogy erőltesse a friss változtatásait.

Ha szerencséd van, az ő helyi tárolójában meglesz a commitok teljes története, a hibádat friss kóddal írják felül, és semmi sem vész el. De mi van, ha nem vagy ilyen szerencsés? Akkor olvass tovább!

1. eset: Te voltál az utolsó, aki a hiba előtt a masterbe pusholt

Jó hír! A szemed előtt van minden, amire szükséged van ahhoz, hogy visszacsináld a hibádat. Csak ne zárd be vagy töröld a terminálodat. Először is menj be a csapatod chatjébe, és gyónd meg a bűneidet. Kérd meg az embereket, hogy a következő egy-két percben ne szórakozzanak a repóval, amíg te javítod a dolgokat.

A shell programodban a git push --force parancs kimenetén keress egy ehhez hasonló sort:

 + deadbeef...f00f00ba master -> master (forced update)

A szimbólumok első csoportja (amely úgy néz ki, mint egy commit SHA előtagja) a megmentés kulcsa. A deadbeef az utolsó jó commitod a master ágba, közvetlenül azelőtt, hogy kárt okoztál volna.

Ezért már csak annyit kell tenned, hogy… erőlteted (tűzzel a tűz ellen!) ezt a commitot vissza a master ágba, egy rossz commit tetejére.

$ git push --force origin deadbeef:master

Gratulálok! Megmentetted a napot. Most itt az ideje, hogy tanulj a hibáidból.

2. eset: a master-t valaki más módosította, mielőtt te elszúrtad

Szóval, pont mielőtt megcsináltad a git push --force-t, valaki bezárt egy csomó pull requestet, és a master most egyáltalán nem úgy néz ki, mint a helyi példányod. Már nem tudod megcsinálni a git push --force sha1:master-et, mivel lokálisan nincsenek friss commitjaid (és a git fetch-el sem tudod megszerezni őket, mert már nem tartoznak egyik ághoz sem). Mégis, maradj nyugodt, és kérd meg a csapattársaidat, hogy egy ideig maradjanak távol a remote-tól.

Nekünk az lesz a hasznunkra, hogy a GitHub nem távolítja el azonnal az elérhetetlen commitokat. Természetesen ezeket sem tudod lehívni, de van egy megoldás.

Megjegyezzük, hogy ez csak akkor fog működni, ha “figyeled” a repository-t, tehát minden, ami benne történik, megjelenik a GitHub címlapján megjelenő feedben. Nyisd meg ezt a feedet, és keress valami ilyesmit:

an hour agoUsername pushed to master at org/repo - deadbeef Implement foo - deadf00d Fix bar

Most már tudod:

  • összeállíthatsz egy https://github.com/org/repo/tree/deadbeef URL-t, ahol deadbeef a sérült ág utolsó jó commitjának hash-ja;
  • megnyithatod a GitHub webes felhasználói felületén az ág/tagváltót;

GitHub branch/tag switcher

GitHub branch/tag switcher

  • Hozzon létre egy nevet egy új ideiglenes ágnak (pl.g., master-before-force-push);
  • Kattints a “Create branch” (ág létrehozása) gombra.

Most már lekérheti az összes hiányzó commitot:

$ git fetchFrom github.com:org/repo * master-before-force-push -> origin/master-before-force-push

A problémája mostantól a korábbi példában leírtakra csökken:

$ git push --force origin origin/master-before-force-push:master

Ha továbbra is szükséged van arra, hogy a munkád a master-ben legyen, egyszerűen csak rebase-elj rá:

$ git rebase origin/master

Hogyan kerüld el az ilyen katasztrófát a jövőben

  1. A GitHub és a GitLab rendelkezik egy “protected branches” nevű funkcióval.” Jelöld meg a master, develop, stable, vagy bármely más fontos ágat védettnek, és senki sem kényszeríthet push-t ezekbe. Mindig van lehetőség egy ág ideiglenes “feloldására”, ha valóban felül kell írni az előzményeket.

    A részletekért olvassa el a GitHub dokumentációját.

  2. A --force opció helyett használja a --force-with-lease opciót. Ez megállítja a push műveletet, ha valaki pusholt ugyanarra az ágra, miközben te dolgoztál rajta (és nem húztál ki semmilyen változtatást).

    Lásd ezt a cikket az Atlassian-tól.

  3. Hozzon létre aliasokat a git push --force-t használó parancsokhoz, hogy elkerülje a véletlen romboló műveleteket:

    # ~/.gitconfig deploy = "!git push --force deis \"$(git rev-parse --abbrev-ref HEAD):master\""

    Olvassa el a ProGit aliasokról szóló fejezetét.

  4. Soha ne végezzen kísérleteket a repository fő ágában! A git checkout -b experiments a legjobb barátod.

Pro tipp: git push számos lehetőséggel rendelkezik. A --force és a --all különösen jól működik együtt. Ezt a kombót akkor használhatod, ha több hónapos inaktivitás után visszatérsz a projekthez. Próbálja ki, ha extra kalandvágyónak érzi magát!

Leave a Reply