Hvordan (og hvorfor!) Sådan holder du din Git-forpligtelseshistorik ren

Forpligtelser er en af nøgledelene i et Git-arkiv, og mere så er forpligtelsesmeddelelsen en livslog for arkivet. Efterhånden som projektet / arkivet udvikler sig over tid (nye funktioner tilføjes, bugs bliver rettet, arkitektur refaktoriseres), er meddelelser om kommission det sted, hvor man kan se, hvad der blev ændret, og hvordan. Så det er vigtigt, at disse meddelelser afspejler den underliggende ændring på en kort, præcis måde.

Hvorfor en meningsfuld Git-forpligtelseshistorik er vigtig

Hvad gør Git-kommission? er de fingeraftryk, du efterlader på den kode, du rører ved. Enhver kode, som du begår i dag, et år fra nu, når du ser på den samme ændring; du ville være taknemmelig for en klar, meningsfuld forpligtelsesmeddelelse, som du skrev, og det vil også gøre livet for dine medudviklere lettere. Når forpligtelser isoleres baseret på kontekst, bliver en fejl, der blev introduceret af en bestemt forpligtelse, hurtigere at finde, og jo lettere er det at tilbageføre den forpligtelse, der forårsagede fejlen i første omgang. / p>

Mens vi arbejder på et stort projekt, beskæftiger vi os ofte med mange bevægelige dele, der opdateres, tilføjes eller fjernes. Det kan være vanskeligt at sikre, at forpligtelsesbeskeder opretholdes i sådanne tilfælde, især når udviklingen spænder over dage, uger eller endda måneder. Så for at forenkle bestræbelserne på at opretholde koncis e commit-historik, denne artikel vil bruge nogle af de almindelige situationer, som en udvikler kan blive udsat for, når han arbejder på et Git-arkiv.

  • Situation 1: Jeg er nødt til at ændre den seneste forpligtelse
  • Situation 2: Jeg har brug for at ændre en bestemt forpligtelse
  • Situation 3: Jeg skal tilføje, fjerne eller kombinere forpligtelser
  • Situation 4: Min forpligtelseshistorik laver ikke fornuft, jeg har brug for en ny start!

Men inden vi dykker ind, lad os hurtigt gennemgå, hvordan en typisk udviklingsworkflow ser ud i en vores hypotetiske Ruby-applikation.

Bemærk: Denne artikel antager, at du er opmærksom på det grundlæggende i Git, hvordan grene fungerer, hvordan du tilføjer uforpligtede ændringer af en gren til scenen, og hvordan du foretager ændringerne. Hvis du er usikker på disse strømme, er vores dokumentation et godt udgangspunkt.

En dag i livet

Her arbejder vi på et lille Ruby on Rails-projekt, hvor vi har brug for at tilføje en navigationsvisning på hjemmesiden, og det involverer opdatering og tilføjelse af flere filer. Følgende er en trinvis opdeling af hele flowet:

  • Du begynder at arbejde på en funktion med opdatering af en fil ; lad “s kalde det application_controller.rb
  • Denne funktion kræver, at du også opdaterer en visning: index.html.haml
  • Du tilføjede en del, der bruges på indekssiden: _navigation.html.haml
  • Stil til siden skal også opdateres for at afspejle den del, vi tilføjede: styles.css.scss
  • Funktionen er nu klar med de ønskede ændringer, tid til også at opdatere test; filer, der skal opdateres, er som følger:
    • application_controller_spec.rb
    • navigation_spec.rb
  • Test opdateres og passerer som forventet, nu er det tid til at foretage ændringerne!

Da alle filerne tilhører forskellige territorier i arkitekturen, forpligter vi os ændringerne isoleret af hinanden for at sikre, at hver forpligtelse repræsenterer en bestemt kontekst og foretages i en bestemt rækkefølge. Jeg foretrækker normalt backend – > frontend-rækkefølge, hvor mest backend-centreret ændring begås først, efterfulgt af mellemlaget og derefter ved frontend-centrerede ændringer i Git-listen forpligter.

Nu hvor vi har foretaget vores ændringer, opretter vi en fusionsanmodning med filialen. Når du har en fletningsanmodning åben, bliver den typisk gennemgået af din peer, før ændringerne flettes i repo “s master gren. Lad os nu lære, hvilke forskellige situationer vi kan ende med under kodegennemgang.

Situation 1: Jeg har brug for at ændre den seneste forpligtelse

Forestil dig et tilfælde, hvor korrekturlæseren kiggede på styles.css.scss og foreslog en ændring. I et sådant tilfælde er det meget simpelt at foretage ændringen, da ændringer i stilarket er en del af den sidste forpligtelse på din gren. Her er hvordan vi kan håndtere dette;

  • Du foretager direkte de nødvendige ændringer til styles.css.scss i din gren.
  • Én gang du er færdig med ændringerne, tilføj disse ændringer til scenen; kør git add styles.css.scss.
  • Når ændringer er iscenesat, skal vi tilføje disse ændringer til vores sidste forpligtelse; kør git commit --amend.
    • Opdeling af kommando: Her beder vi kommandoen git commit om at ændre de ændringer, der findes i trin til den seneste forpligtelse.
  • Dette åbner din sidste forpligtelse i din Git-definerede teksteditor, der har kommitteringsmeddelelsen Tilføj typografier til navigation.
  • Da vi kun opdaterede CSS-erklæringen, behøver vi ikke ændre meddelelsen.På dette tidspunkt kan du bare gemme og afslutte teksteditoren, som Git åbnede for dig, og dine ændringer vil blive afspejlet i forpligtelsen.

Da du ændrede en eksisterende forpligtelse, er disse ændringer nødvendige for at blive tvunget til din eksterne repo ved hjælp af git push --force-with-lease <remote_name> <branch_name>. Denne kommando tilsidesætter forpligtelsen Add styles for navigation på ekstern repo med opdateret commit, som vi lige har lavet i vores lokale repo.

En ting at huske på, mens du presser på grene er, at hvis du arbejder på den samme gren med flere personer, kan tvangsskubning forårsage problemer for andre brugere, når de normalt forsøger at skubbe deres ændringer til en fjerntliggende gren, der har skubbet nye forpligtelsesstyrker. Brug derfor denne funktion klogt. Du kan lære mere om Git force push-muligheder her.

Situation 2: Jeg har brug for at ændre et specifikt engagement

I den tidligere situation var løsningen ret enkel, da vi var nødt til at ændre kun vores sidste Git-forpligtelse, men forestil dig, hvis korrekturlæser foreslog at ændre noget i _navigation.html.haml. I dette tilfælde er det anden forpligtelse fra toppen, så ændring af det vil ikke være så direkte som det var i den første situation. Lad os se, hvordan vi kan håndtere dette:

Når en forpligtelse er lavet i en gren, er det identificeret ved en unik SHA1 hash-streng. Tænk på det som et unikt ID, der adskiller en forpligtelse fra en anden. Du kan se alle forpligtelserne sammen med deres SHA1-hashes i en gren ved at køre git log. Med dette vil du se en output, der ser noget ud som følger, hvor de seneste forpligtelser er øverst;

Det er her git rebase kommando kommer i spil. Hver gang vi ønsker at redigere en bestemt forpligtelse med git rebase, er vi nødt til først at basere vores gren igen ved at flytte HEAD tilbage til det punkt lige før den forpligtelse, vi ønsker at redigere. I vores tilfælde er vi nødt til at ændre den forpligtelse, der læser Page Navigation View.

Her skal du bemærke hash af begå, som er lige før den forpligtelse, vi vil ændre; kopier hash og udfør følgende trin:

  • Sæt grenen tilbage for at flytte til at begå, før vores målforpligtelse; kør git rebase -i 8d74af102941aa0b51e1a35b8ad731284e4b5a20
    • Opdeling af kommando: Her kører vi Git “s rebase kommando med interaktiv tilstand med forudsat SHA1-hash som forpligtelse til at rebase til.
  • Dette kører rebase-kommandoen for Git i interaktiv tilstand og åbner din teksteditor, der viser alle dine forpligtelser, der kom efter den forpligtelse, du rebasede til . Det vil se sådan ud:

Bemærk, hvordan hver forpligtelse har et ord pick foran det og i indholdet nedenfor er der alle mulige nøgleord, vi kan bruge. Da vi ønsker at redigere en forpligtelse, skal vi ændre pick 4155df1cdc7 Page Navigation View til edit 4155df1cdc7 Page Navigation View. Gem ændringerne, og afslut editoren.

Nu er din filial rebaseret til tidspunktet lige før den forpligtelse, du foretog, som indeholdt _navigation.html.haml. Åbn filen, og udfør de ønskede ændringer i henhold til tilbagemeldingen. Når du er færdig med ændringerne, skal du iscenesætte dem ved at køre git add _navigation.html.haml.

Da vi har iscenesat ændringerne, er det tid til at flytte gren HEAD tilbage til begå, som vi oprindeligt havde (mens vi også inkluderer de nye ændringer, vi tilføjede), kør git rebase --continue, dette åbner din standardeditor i terminalen og viser dig den meddelelsesmeddelelse, som vi redigerede under rebase; Page Navigation View. Du kan ændre denne besked, hvis du ønsker det, men vi vil lade det være, som det er for nu, så gem og luk redaktøren. På dette tidspunkt vil Git afspille alle forpligtelserne igen der fulgte efter den forpligtelse, du lige har redigeret, og nu er filial HEAD tilbage til den øverste forpligtelse, vi oprindeligt havde, og den inkluderer også de nye ændringer, du foretog i en af forpligtelserne.

Da vi igen har ændret en forpligtelse, som “allerede findes i ekstern repo, har vi brug for kraft, skub denne gren igen ved hjælp af git push --force-with-lease <remote_name> <branch_name>.

Situation 3 : Jeg skal tilføje, fjerne eller kombinere forpligtelser

En almindelig situation er, når du har lavet flere forpligtelser bare for at rette op på noget, der tidligere er begået. Lad os nu reducere dem så meget som muligt, og kombinere dem med de oprindelige forpligtelser.

Alt du skal gøre er at starte den interaktive rebase, som du ville gjort i de andre scenarier.

Forestil dig nu, at du vil kombinere alle disse rettelser i c22a3fa0c5c Render navigation partial. Du skal bare:

  1. Flyt rettelserne op, så de er lige under den forpligtelse, du til sidst vil beholde.
  2. Skift pick til squash eller fixup for hver af rettelserne.

Bemærk: squash gemmer de kommitterede meddelelser i beskrivelsen. fixup glemmer rettelsesmeddelelsernes forpligtelsesmeddelelser og beholder originalen.

Du vil ende med noget som dette:

Gem ændringerne, afslut editoren , og du er færdig! Dette er den resulterende historie:

Som før er alt hvad du skal gøre nu git push --force-with-lease <remote_name> <branch_name> og ændringerne er ope.

Hvis du vil fjerne commit fra grenen helt, i stedet for squash eller fixup, skriv bare drop eller bare slet den linje.

Undgå konflikter

For at undgå konflikter skal du sørge for, at det forpligter dig “at flytte op på tidslinjen er ikke ved at røre ved de samme filer, der berøres af de forpligtelser, der er tilbage efter dem.

Pro-tip : Hurtige rettelser

Hvis du ved nøjagtigt, hvilken forpligtelse du vil rette, når du forpligter dig, behøver du ikke spilde hjernecyklusser i at tænke på gode midlertidige navne til “Fix 1”, “Fix 2”,…, “Fix 42”.

Trin 1: Mød --fixup

Når du har iscenesat ændringerne, der løser hvad det er, der skal rettes, bare Git begår alle ændringer sådan:

(Bemærk, at dette er hash for kommit c22a3fa0c5c Render navigation partial)

Dette vil generere denne meddelelse om forpligtelse: fixup! Render navigation partial.

Trin 2: Og sidekick --autosquash

Nem interaktiv rebase. Du kan få git til at placere fixup s på det rigtige sted.

git rebase -i 4155df1cdc7 --autosquash

Historik vises som sådan:

Klar til at du bare gennemgå og fortsæt.

Hvis du føler dig eventyrlysten, kan du lave en ikke-interaktiv rebase git rebase --autosquash, men kun hvis du kan lide at leve farligt, som du “ll har ingen mulighed for at gennemgå de squasher, der bliver lavet, før de “anvendes igen.

Situation 4: Min Git-begivenhedshistorik giver ikke mening, jeg har brug for en ny start!

Hvis vi “arbejder på en stor funktion, er det almindeligt at have flere ændringer i fixup- og gennemgangsfeedback, der ofte begås. I stedet for konstant at rebase filialen kan vi lade oprydning af forpligtelser være indtil slutningen af udviklingen.

Dette er hvor oprettelse af patch-filer er meget praktisk. Faktisk var patch-filer den primære måde at dele kode via e-mail, mens du samarbejder på store open source-projekter, før Git-baserede tjenester som GitLab var tilgængelige for udviklere. Forestil dig, at du har en sådan gren (f.eks. add-page-navigation), hvor der er masser af forpligtelser, der ikke overfører de underliggende ændringer tydeligt. Her kan du oprette en patch-fil til alle de ændringer, du har foretaget i denne gren:

  • Det første skridt til at oprette patchfilen er at sikre dig, at din gren har alle de ændringer, der er til stede fra master filial og har ingen konflikter med det samme.
  • Du kan køre git rebase master eller git merge master mens du “kontrolleres igen ud i add-page-navigation gren for at få alle ændringerne fra master til din gren.
  • Opret nu patch-filen ; kør git diff master add-page-navigation > ~/add_page_navigation.patch.
    • Opdeling af kommando: Her bruger vi Gits diff-funktion og beder om en forskel mellem master filial og add-page-navigation gren og omdirigerer output (via > symbol) til en fil med navnet add_page_navigation.patch i vores os er hjemmekatalog (typisk ~/ i * nix-operativsystemer).
  • Du kan angive enhver sti, du vil beholde denne fil ind, og filnavnet og filtypen kan være alt hvad du vil.
  • Når kommandoen er kørt, og du ikke kan se nogen fejl, genereres patchfilen.
  • Tjek nu master gren; kør git checkout master.
  • Slet grenen add-page-navigation fra lokal repo; kør git branch -D add-page-navigation. Husk, vi har allerede ændringer af denne gren i en oprettet patchfil.
  • Opret nu en ny gren med samme navn (mens master er tjekket ud); kør git checkout -b add-page-navigation.
  • På dette tidspunkt er dette en frisk gren og har ingen af dine ændringer.
  • Endelig skal du anvende dine ændringer fra patch-filen; git apply ~/add_page_navigation.patch.
  • Her anvendes alle dine ændringer i en gren, og de ser ud som uforpligtede, som om al din ændring hvor det er gjort, men ingen af ændringerne blev faktisk begået i grenen.
  • Nu kan du fortsætte med at begå individuelle filer eller filer grupperet efter påvirkningsområde i den rækkefølge, du ønsker, med kortfattede forpligtelsesmeddelelser.

Som med tidligere situationer ændrede vi grundlæggende hele grenen, så det er på tide at tvinge push!

Konklusion

Selvom vi har dækket de mest almindelige og grundlæggende situationer, der opstår i en daglig arbejdsgang med Git, er omskrivning af Git-historie et stort emne, og som du bliver fortrolig med ovenstående tip kan du lære mere avancerede koncepter omkring emnet i Git Official Documentation. Happy git “ing!

Foto af pan xiaozhen på Unsplash

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *