git push –force en hoe er mee om te gaan

Heb je jezelf ooit in een situatie bevonden waar een verkeerd git commando een ravage aanrichtte in de repo van je project? Mensen maken fouten, en soms kunnen die fouten uren van de tijd van je team kosten. In deze tutorial laten we je zien hoe je snel van een ongelukkige git push --force kunt herstellen.

Laten we niet al te zelfverzekerd worden. Vroeg of laat, gaat dit gebeuren. Als je met meerdere remotes in dezelfde git repository werkt, zul je uiteindelijk git push --force in master (of een andere belangrijke branch waar je nooit mee moet knoeien).

Dat kan bijvoorbeeld gebeuren bij het deployen met Deis of Heroku die aparte git remotes gebruiken om een applicatie te bouwen en deployen. Na een lange dag werken, is het ongelooflijk gemakkelijk om git push --force uit te voeren in plaats van de gebruikelijke git push --force deis master.

Oeps! In een oogwenk, hebben je teamgenoten al hun laatste werk verloren. Tijd om hun woede onder ogen te zien.

Hoewel, zoals een uitstekende gids ons vertelt, DON’t PANIC! Het goede ding is, je gebruikt git, en dat betekent dat alles kan worden gerepareerd.

Best case scenario: iemand anders die werkt aan dezelfde code trok een recente versie van de master net voordat je het brak. Dan hoef je alleen maar in de chat van je team te gaan en die persoon te vragen om zijn recente wijzigingen geforceerd te pushen.

Als je geluk hebt, zal hun lokale repository de volledige geschiedenis van commits hebben, je fout zal worden overschreven met verse code, en er zal niets verloren gaan. Maar wat als je niet zoveel geluk hebt? Lees dan verder!

Geval 1: Je was de laatste persoon die naar master heeft gepushed voor de fout

Goed nieuws! U heeft alles wat u nodig heeft om uw fout ongedaan te maken voor uw eigen ogen. Sluit of verwijder gewoon je terminal niet. Ga eerst naar de chat van je team en biecht je zonden op. Vraag mensen om de komende minuut niet met de repo te rommelen terwijl jij dingen repareert.

In de uitvoer van git push --force commando in je shell zoek je naar een regel die op deze lijkt:

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

De eerste groep symbolen (die eruit ziet als de SHA prefix van een commit) is de sleutel tot de redding. deadbeef is je laatste goede commit naar de master net voordat je schade toebracht.

Dus alles wat je nodig hebt is om… deze commit terug te forceren (vuur met vuur bestrijden!) naar de master branch, bovenop een slechte.

$ git push --force origin deadbeef:master

Gefeliciteerd! Je hebt de dag gered. Nu is het tijd om van je fouten te leren.

Geval 2: de master is door iemand anders gewijzigd voordat jij het verknalde

Dus, net voordat je git push --force deed, had iemand een heleboel pull requests gesloten, en de master lijkt nu in niets meer op je lokale kopie. Je kunt git push --force sha1:master niet meer doen omdat je geen recente commits lokaal hebt (en je kunt ze ook niet krijgen met git fetch omdat ze niet meer bij een branch horen). Toch, blijf kalm en vraag je teamgenoten om een tijdje van de remote af te blijven.

We zullen profiteren van het feit dat GitHub onbereikbare commits niet direct verwijdert. Natuurlijk kun je ze ook niet ophalen, maar er is een workaround.

Merk op dat het alleen zal werken als je de repository “in de gaten houdt”, zodat alles wat erin gebeurt in een feed verschijnt die op de voorpagina van je GitHub staat. Open die feed en kijk naar iets als dit:

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

Nu kun je:

  • Een URL https://github.com/org/repo/tree/deadbeef samenstellen, waarbij deadbeef een hash is van de laatste goede commit naar de beschadigde branch;
  • De branches/tags switcher in de web UI van GitHub openen;

GitHub branch/tag switcher

GitHub branch/tag switcher

  • Creëer een naam voor een nieuwe tijdelijke branch (bijv.g., master-before-force-push);
  • Klik op “Tak aanmaken”.

Nu kunt u alle ontbrekende commits ophalen:

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

Uw probleem is nu gereduceerd tot het probleem dat in een eerder voorbeeld is beschreven:

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

Als je nog steeds je werk in de master nodig hebt, baseer je er gewoon opnieuw bovenop:

$ git rebase origin/master

Hoe voorkom je zo’n ramp in de toekomst

  1. GitHub en GitLab hebben een functie genaamd “protected branches.” Markeer master, develop, stable, of elke andere cruciale branch als protected en niemand zal toegestaan worden om er een push in te forceren. Het is altijd mogelijk om tijdelijk een branch te “unprotecten” als je echt de historie moet overschrijven.

    Lees de GitHub docs voor details.

  2. In plaats van --force optie, gebruik --force-with-lease. Het zal de push operatie stoppen als iemand naar dezelfde branch heeft gepushed terwijl jij er mee bezig was (en geen wijzigingen hebt opgehaald).

    Zie dit artikel van Atlassian.

  3. Maak aliassen voor commando’s die git push --force gebruiken om per ongeluk destructieve acties te voorkomen:

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

    Lees het ProGit hoofdstuk over aliassen.

  4. Nooit je experimenten doen in de hoofd branch van een repository! git checkout -b experiments is je beste vriend.

Pro Tip: git push heeft veel opties. --force en --all werken bijzonder goed samen. U kunt deze combo gebruiken wanneer u terugkeert naar het project na enkele maanden van inactiviteit. Probeer het eens als u extra avontuurlijk bent!

Leave a Reply