git push –force and how to deal with it

Har du nogensinde befundet dig i en situation, hvor en forkert git-kommando har forårsaget ravage i dit projekts repo? Folk begår fejl, og nogle gange kan disse fejl koste timer af dit teams tid. I denne vejledning vil vi vise dig, hvordan du hurtigt kan komme dig efter en uheldig git push --force.

Lad os ikke blive for selvsikker. Før eller senere vil dette ske. Når du arbejder med flere remotes i det samme git-repositorium, vil du til sidst git push --force ind i master (eller en anden vigtig gren, som der aldrig bør rodes med).

Det kan f.eks. ske, når du udruller med Deis eller Heroku, der bruger separate git-remotes til at bygge og udrulle en applikation. Efter en lang arbejdsdag er det utrolig nemt at udføre git push --force i stedet for det sædvanlige git push --force deis master.

Ops! I løbet af et øjeblik har dine holdkammerater mistet alt deres seneste arbejde. Tid til at se deres raseri i øjnene.

Men som en fremragende guide fortæller os: DON’T PANIC! Det gode er, at du bruger git, og det betyder, at alt kan rettes.

Best case scenario: En anden, der arbejder på den samme kode, har trukket en nyere version af master lige før du ødelagde den. Så er det eneste, du skal gøre, at gå ind i dit teams chat og bede den pågældende person om at tvinge deres seneste ændringer til at pushes.

Hvis du er heldig, vil deres lokale repository have den fulde historik over commits, din fejl vil blive overskrevet med frisk kode, og intet vil gå tabt. Men hvad nu hvis du ikke er så heldig? Så læs videre!

Fald 1: Du var den sidste person, der pushede til master før fejlen

Gode nyheder! Du har alt, hvad du behøver for at fortryde din fejl, lige foran dine øjne. Du må bare ikke lukke eller rydde din terminal. Først skal du gå ind i dit holds chat og tilstå dine synder. Bed folk om ikke at rode med repo’en i det næste minut eller to, mens du retter tingene.

I output af git push --force-kommandoen i din shell skal du lede efter en linje, der ligner denne:

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

Den første gruppe af symboler (som ligner et commit’s SHA-præfiks) er nøglen til redningen. deadbeef er dit sidste gode commit til master lige før du påførte skade.

Så alt du behøver er at… force push (bekæmpe ild med ild!) dette commit tilbage til master-grenen, ovenpå et dårligt commit.

$ git push --force origin deadbeef:master

Godt tillykke! Du har reddet dagen. Nu er det tid til at lære af dine fejltagelser.

Fald 2: Master blev ændret af en anden, før du lavede rod i det

Så, lige før du lavede git push --force havde nogen lukket en masse pull requests, og master ligner nu slet ikke din lokale kopi. Du kan ikke længere lave git push --force sha1:master, da du ikke har de seneste commits lokalt (og du kan ikke få dem med git fetch, da de ikke længere hører til nogen branch). Bevar alligevel roen og bed dine holdkammerater om at holde sig fra fjernbetjeningen i et stykke tid.

Vi vil drage fordel af, at GitHub ikke fjerner utilgængelige commits med det samme. Du kan selvfølgelig heller ikke hente dem, men der er en løsning.

Bemærk, at det kun virker, hvis du “overvåger” repositoryet, så alt, hvad der sker i det, vises i et feed, der vises på din GitHubs forside. Åbn dette feed, og kig efter noget som dette:

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

Nu kan du:

  • Sammensæt en URL https://github.com/org/repo/tree/deadbeef, hvor deadbeef er en hash af det sidste gode commit til den beskadigede gren;
  • Åbn branches/tags-switcher i GitHubs webbrugergrænseflade;

GitHub branch/tag switcher

GitHub branch/tag switcher

  • Opret et navn til en ny midlertidig gren (f.eks.g., master-before-force-push);
  • Klik på “Opret gren”.

Nu kan du hente alle manglende commits:

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

Dit problem er nu reduceret til det, der er beskrevet i et tidligere eksempel:

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

Hvis du stadig har brug for, at dit arbejde skal være i master, så skal du bare rebasere ovenpå det:

$ git rebase origin/master

Sådan undgår du en sådan katastrofe i fremtiden

  1. GitHub og GitLab har en funktion, der hedder “beskyttede grene”.” Markér master, develop, stable eller andre vigtige grene som beskyttede, og ingen vil få lov til at tvinge push til dem. Det er altid muligt midlertidigt at “ophæve beskyttelsen” af en gren, hvis du virkelig har brug for at overskrive historikken.

    Læs GitHub-dokumentationen for detaljer.

  2. I stedet for --force-indstillingen skal du bruge --force-with-lease. Det vil stoppe push-operationen, hvis nogen har pushet til den samme gren, mens du arbejdede på den (og ikke har trukket nogen ændringer).

    Se denne artikel fra Atlassian.

  3. Opret aliaser til kommandoer, der bruger git push --force, for at forhindre destruktive handlinger ved et uheld:

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

    Læs ProGit-kapitlet om aliaser.

  4. Leg aldrig dine eksperimenter i hovedgrenen af et repository! git checkout -b experiments er din bedste ven.

Pro Tip: git push har mange muligheder. --force og --all fungerer særligt godt sammen. Du kan bruge denne kombi, når du vender tilbage til projektet efter flere måneders inaktivitet. Giv den et forsøg, hvis du føler dig ekstra eventyrlysten!

Leave a Reply