Hur (och varför!) Att hålla din Git-engagemangshistoria ren

Åtaganden är en av de viktigaste delarna i ett Git-arkiv, och mer så är engagemangsmeddelandet en livslogg för förvaret. När projektet / förvaret utvecklas över tiden (nya funktioner läggs till, buggar fixas, arkitektur refaktoreras), är kommuniceringsmeddelanden den plats där man kan se vad som har ändrats och hur. Så det är viktigt att dessa meddelanden återspeglar den underliggande förändringen på ett kort, exakt sätt.

Varför en meningsfull Git-engagemangshistorik är viktig

Vad gör Git-kommittén gör? är fingeravtrycken som du lämnar på koden du rör vid. Alla koder som du gör idag, ett år från och med nu när du tittar på samma förändring. Du skulle vara tacksam för ett tydligt, meningsfullt meddelande som du skrev, och det kommer också gör livet för dina medutvecklare enklare. När åtaganden isoleras baserat på sammanhang blir ett fel som introducerades av ett visst engagemang snabbare att hitta, och desto lättare är det att återställa det åtagande som orsakade felet i första hand. / p>

Medan vi arbetar med ett stort projekt, hanterar vi ofta många rörliga delar som uppdateras, läggs till eller tas bort. Att säkerställa att kommunicera meddelanden upprätthålls i sådana fall kan vara svårt, särskilt när utvecklingen sträcker sig över dagar, veckor eller till och med månader. Så för att förenkla ansträngningen att behålla koncis e commit-historia, den här artikeln kommer att använda några av de vanliga situationerna som en utvecklare kan möta när han arbetar med ett Git-arkiv.

  • Situation 1: Jag måste ändra det senaste engagemanget
  • Situation 2: Jag måste ändra ett specifikt engagemang
  • Situation 3: Jag måste lägga till, ta bort eller kombinera åtaganden
  • Situation 4: Min åtagandeshistorik gör inte känsla, jag behöver en ny start!

Men innan vi dyker in, låt oss snabbt gå igenom hur ett typiskt utvecklingsarbetsflöde ser ut i en vår hypotetiska Ruby-applikation.

Obs! Den här artikeln förutsätter att du är medveten om grunderna i Git, hur filialer fungerar, hur man lägger till obundna ändringar av en gren till scenen och hur man gör ändringarna. Om du är osäker på dessa flöden är vår dokumentation en bra utgångspunkt.

En dag i livet

Här arbetar vi med ett litet Ruby on Rails-projekt där vi måste lägga till en navigeringsvy på hemsidan och det innebär att uppdatera och lägga till flera filer. Nedan följer en stegvis uppdelning av hela flödet:

  • Du börjar arbeta med en funktion med att uppdatera en fil ; låt oss kalla det application_controller.rb
  • Denna funktion kräver att du också uppdaterar en vy: index.html.haml
  • Du har lagt till en del som används på indexsidan: _navigation.html.haml
  • Stilar för sidan måste också uppdateras för att återspegla den partiella som vi lagt till: styles.css.scss
  • Funktionen är nu redo med önskade ändringar, det är dags att också uppdatera tester; filer som ska uppdateras är följande:
    • application_controller_spec.rb
    • navigation_spec.rb
  • Tester uppdateras och passerar som förväntat, nu är det dags att göra ändringarna!

Eftersom alla filer tillhör olika arkitekturområden, åtar vi oss förändringarna isolerade från varandra för att säkerställa att varje åtagande representerar ett visst sammanhang och görs i en viss ordning. Jag brukar föredra backend – > frontend-ordning där de flesta backend-centrerade förändringar görs först, följt av mellanlagret och sedan av frontend-centrerade ändringar i Git-listan.

Nu när vi har gjort våra ändringar skapar vi en sammanslagningsförfrågan med filialen. När du har en sammanslagningsbegäran öppen granskas den vanligtvis av din kollega innan ändringarna slås samman till repo ”s master gren. Låt oss nu lära oss vilka olika situationer vi kan hamna i under kodgranskning.

Situation 1: Jag måste ändra det senaste åtagandet

Föreställ dig ett fall där granskaren tittade på styles.css.scss och föreslog en förändring. I ett sådant fall är det väldigt enkelt att göra ändringen, eftersom ändringar av formatmallen är en del av den senaste förpliktelsen på din gren. Så här kan vi hantera detta;

  • Du gör direkt de nödvändiga ändringarna av styles.css.scss i din gren.
  • En gång du är klar med ändringarna, lägg till dessa ändringar i scenen; kör git add styles.css.scss.
  • När ändringarna är iscensatta måste vi lägga till dessa ändringar i vårt senaste engagemang; kör git commit --amend.
    • Uppdelning av kommando: Här ber vi kommandot git commit att ändra de ändringar som finns i steg till det senaste engagemanget.
  • Detta öppnar ditt senaste engagemang i din Git-definierade textredigerare som har kommuniceringsmeddelandet Lägg till stilar för navigering.
  • Eftersom vi bara uppdaterade CSS-deklarationen behöver vi inte ändra meddelandet.Nu kan du bara spara och avsluta textredigeraren som Git öppnade för dig och dina ändringar kommer att återspeglas i engagemanget.

Eftersom du ändrade ett befintligt engagemang krävs dessa ändringar. för att tvingas pressas till din fjärranslutning med git push --force-with-lease <remote_name> <branch_name>. Det här kommandot åsidosätter kommittén Add styles for navigation på fjärrrepo med uppdaterad kommission som vi just gjorde i vårt lokala repo.

En sak att tänka på medan du tvingar på grenar är att om du arbetar på samma gren med flera personer, kan krafttryckning orsaka problem för andra användare när de normalt försöker trycka på sina ändringar på en avlägsen gren som har fått nytt kraft. Använd därför den här funktionen klokt. Du kan lära dig mer om Git force push-alternativ här.

Situation 2: Jag måste ändra ett specifikt engagemang

I den tidigare situationen var fixen ganska enkel eftersom vi var tvungna att ändra bara vårt senaste Git-åtagande, men tänk dig om granskaren föreslog att ändra något i _navigation.html.haml. I det här fallet är det andra åtagandet uppifrån, så att ändra det kommer inte att vara lika direkt som det var i den första situationen. Låt oss se hur vi kan hantera detta:

När ett engagemang är tillverkad i en gren identifieras den av en unik SHA1-hashsträng. Tänk på det som ett unikt ID som skiljer ett åtagande från ett annat. Du kan se alla åtaganden tillsammans med deras SHA1-hash i en gren genom att köra git log. Med detta skulle du se en utdata som ser ungefär så ut, där de senaste åtagandena är högst upp;

Det är här git rebase kommandot spelar in. Närhelst vi vill redigera ett specifikt engagemang med git rebase, måste vi först basera vår gren igen genom att flytta tillbaka HEAD till punkten precis före det engagemang vi vill redigera. I vårt fall måste vi ändra åtagandet som läser Page Navigation View.

Här, märk hash of commit som ligger precis före det commit vi vill ändra; kopiera hash och utför följande steg:

  • Förgrena filialen för att flytta att begå innan vårt målplikt; kör git rebase -i 8d74af102941aa0b51e1a35b8ad731284e4b5a20
    • Kommandouppdelning: Här kör vi Git ”s rebase kommando med interaktivt läge med tillhandahållen SHA1-hash som åtagande att rebase till.
  • Detta kommer att köra rebase-kommandot för Git i interaktivt läge och öppnar din textredigerare som visar alla dina åtaganden som kom efter det åtagande du satsade på . Det kommer att se ut så här:

Lägg märke till hur varje engagemang har ett ord pick framför det och i innehållet nedan finns alla möjliga nyckelord vi kan använda. Eftersom vi vill redigera ett engagemang måste vi ändra pick 4155df1cdc7 Page Navigation View till edit 4155df1cdc7 Page Navigation View. Spara ändringarna och avsluta redigeraren.

Nu baseras din filial till tidpunkten precis före det åtagande du gjorde som innehöll _navigation.html.haml. Öppna filen och utför önskade ändringar enligt recensionens feedback. När du är klar med ändringarna, stegvisa dem genom att köra git add _navigation.html.haml.

Eftersom vi har iscensatt ändringarna är det dags att flytta gren HEAD tillbaka till commit som vi ursprungligen hade (samtidigt som vi inkluderade de nya ändringarna som vi lagt till), kör git rebase --continue, detta öppnar din standardredigerare i terminalen och visar dig kommuniceringsmeddelandet som vi redigerade under rebase; Page Navigation View. Du kan ändra detta meddelande om du vill, men vi skulle lämna det som det är för tillfället, så spara och avsluta redigeraren. Vid den här tiden spelar Git upp alla åtaganden som följde efter att du just redigerat och nu är grenen HEAD tillbaka till det bästa engagemanget som vi ursprungligen hade, och det inkluderar också de nya ändringarna du gjorde i ett av åtagandena.

Eftersom vi återigen modifierade ett engagemang som ”redan finns i fjärranslutning, behöver vi kraft trycka på den här grenen igen med git push --force-with-lease <remote_name> <branch_name>.

Situation 3 : Jag måste lägga till, ta bort eller kombinera åtaganden

En vanlig situation är när du har gjort flera åtaganden bara för att fixa något som begåtts tidigare. Låt oss nu minska dem så mycket vi kan och kombinera dem med de ursprungliga åtagandena.

Allt du behöver göra är att starta den interaktiva rebasen som du skulle göra i de andra scenarierna.

Tänk dig nu att du vill kombinera alla dessa korrigeringar i c22a3fa0c5c Render navigation partial. Du behöver bara:

  1. Flytta korrigeringarna uppåt så att de ligger precis under det engagemang du vill behålla till slut.
  2. Ändra pick till squash eller fixup för var och en av korrigeringarna.

Obs: squash behåller kommit-meddelandena i beskrivningen. fixup kommer att glömma fix-meddelandets meddelanden och behålla originalet.

Du kommer att sluta med något så här:

Spara ändringarna, avsluta redigeraren , och du är klar! Detta är den resulterande historiken:

Som tidigare är allt du behöver göra nu git push --force-with-lease <remote_name> <branch_name> och ändringarna är uppe.

Om du vill ta bort engagemang från filialen helt, istället för squash eller fixup, skriv bara drop eller radera bara den raden.

Undvik konflikter

För att undvika konflikter, se till att åtagandena ”flyttar upp på tidslinjen är inte vidrör samma filer som berörs av de åtaganden som finns kvar efter dem.

Pro-tip : Snabbkorrigeringar

Om du vet exakt vilket engagemang du vill fixa, behöver du inte slösa hjärncykler när du begår att tänka på bra tillfälliga namn för ”Fix 1”, ”Fix 2”, …, ”Fix 42”.

Steg 1: Möt --fixup

När du har iscensatt ändringarna för att fixa vad som än behöver fixas, bara Git gör alla ändringar så här:

(Observera att detta är hash för kommittén c22a3fa0c5c Render navigation partial)

Detta kommer att generera detta meddelande: fixup! Render navigation partial.

Steg 2: Och sidokick --autosquash

Enkel interaktiv rebase. Du kan få git placera fixup s på rätt plats.

git rebase -i 4155df1cdc7 --autosquash

Historiken visas så:

Redo för dig att bara granska och fortsätt.

Om du känner dig äventyrlig kan du göra en icke-interaktiv rebase git rebase --autosquash, men bara om du gillar att leva farligt, som du ” har ingen möjlighet att granska de squashar som görs innan de ”tillämpas igen.

Situation 4: My Git commit history betyder inte meningsfullt, jag behöver en ny start!

Om vi ”arbetar med en stor funktion, det är vanligt att ha flera fixup- och recension-feedback-förändringar som görs ofta. I stället för att ständigt omgränsa filialen kan vi lämna rensningen av åtaganden till slutet av utvecklingen.

Det är här det är extremt praktiskt att skapa patchfiler. I själva verket var patchfiler det primära sättet att dela kod via e-post medan man samarbetade på stora open source-projekt innan Git-baserade tjänster som GitLab var tillgängliga för utvecklare. Tänk dig att du har en sådan gren (t.ex.; add-page-navigation) där det finns massor av åtaganden som inte förmedlar de underliggande förändringarna tydligt. Så här kan du skapa en korrigeringsfil för alla ändringarna du gjorde i den här grenen:

  • Det första steget för att skapa korrigeringsfilen är att se till att din filial har alla ändringar från master filial och har inga konflikter med samma.
  • Du kan köra git rebase master eller git merge master medan du kontrollerar ute i add-page-navigation gren för att få alla ändringar från master till din gren.
  • Skapa nu korrigeringsfilen ; kör git diff master add-page-navigation > ~/add_page_navigation.patch.
    • Uppdelning av kommando: Här använder vi Gits diff-funktion och ber om en skillnad mellan master gren och add-page-navigation gren och omdirigerar utdata (via > symbol) till en fil med namnet add_page_navigation.patch i vår oss hemkatalog (vanligtvis ~/ i * nix-operativsystem).
  • Du kan ange vilken sökväg du vill behålla den här filen in och filnamnet och tillägget kan vara vad du vill.
  • När kommandot har körts och du inte ser några fel genereras korrigeringsfilen.
  • Kassa nu master gren; kör git checkout master.
  • Ta bort grenen add-page-navigation från lokal repo; kör git branch -D add-page-navigation. Kom ihåg att vi redan har ändringar av den här grenen i en skapad korrigeringsfil.
  • Skapa nu en ny gren med samma namn (medan master är utcheckad); kör git checkout -b add-page-navigation.
  • Vid denna tidpunkt är det här en ny gren och har inga av dina ändringar.
  • Slutligen, använd dina ändringar från korrigeringsfilen; git apply ~/add_page_navigation.patch.
  • Här tillämpas alla dina ändringar i en gren och de kommer att se ut som obundna, som om alla dina ändringar där gjort, men ingen av ändringarna gjordes faktiskt i grenen.
  • Nu kan du fortsätta och begå enskilda filer eller filer grupperade efter påverkningsområde i den ordning du vill ha med kortfattade meddelanden.

Som med tidigare situationer ändrade vi i princip hela grenen, så det är dags att tvinga push!

Slutsats

Även om vi har täckt över de vanligaste och grundläggande situationerna som uppstår i ett dagligt arbetsflöde med Git, är omskrivning av Git-historia ett stort ämne och som du blir bekant med ovanstående tips kan du lära dig mer avancerade begrepp kring ämnet i Git Official Documentation. Happy git ”ing!

Foto av pan xiaozhen på Unsplash

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *