Hoe (en waarom!) Je Git-commit-geschiedenis schoon te houden

Commits zijn een van de belangrijkste onderdelen van een Git-repository, en meer nog, het vastlegbericht is een levenslogboek voor de repository. Naarmate het project / de repository in de loop van de tijd evolueert (nieuwe functies worden toegevoegd, bugs worden opgelost, architectuur wordt opnieuw ontworpen), zijn commit-berichten de plek waar men kan zien wat er is veranderd en hoe. Het is dus belangrijk dat deze berichten de onderliggende verandering op een korte, precieze manier weergeven.

Waarom is een zinvolle Git commit-geschiedenis belangrijk

Wat doet Git commit? Git commit-berichten zijn de vingerafdrukken die u achterlaat op de code die u aanraakt. Elke code die u vandaag vastlegt, een jaar vanaf nu wanneer u naar dezelfde wijziging kijkt; u zou dankbaar zijn voor een duidelijk, zinvol vastleggingsbericht dat u hebt geschreven, en het zal ook maak het leven van je mede-ontwikkelaars gemakkelijker. Wanneer commits worden geïsoleerd op basis van context, wordt een bug die werd geïntroduceerd door een bepaalde commit sneller gevonden, en des te gemakkelijker is het om de commit terug te draaien die de bug in de eerste plaats veroorzaakte. / p>

Terwijl we aan een groot project werken, hebben we vaak te maken met veel bewegende delen die worden bijgewerkt, toegevoegd of verwijderd. Het kan lastig zijn om ervoor te zorgen dat vastleggingsberichten worden gehandhaafd, vooral wanneer de ontwikkeling zich over dagen uitstrekt, weken of zelfs maanden, dus om de moeite van het handhaven van beknoptheid te vereenvoudigen e commit geschiedenis, zal dit artikel enkele van de veelvoorkomende situaties gebruiken waarmee een ontwikkelaar te maken kan krijgen tijdens het werken aan een Git repository.

  • Situatie 1: ik moet de meest recente commit wijzigen
  • Situatie 2: ik moet een specifieke commit wijzigen
  • Situatie 3: ik moet commits toevoegen, verwijderen of combineren
  • Situatie 4: mijn commit-geschiedenis maakt niet zin, ik heb een nieuwe start nodig!

Maar voordat we erin duiken, laten we eerst eens kijken hoe een typische ontwikkelingsworkflow eruitziet in een onze hypothetische Ruby-applicatie.

Opmerking: dit artikel gaat ervan uit dat je op de hoogte bent van de basis van Git, hoe branches werken, hoe je niet-gecommitteerde wijzigingen van een branch aan het podium toevoegt en hoe je de wijzigingen doorvoert. Als u niet zeker bent van deze stromen, is onze documentatie een goed startpunt.

Een dag in het leven

Hier werken we aan een klein Ruby on Rails-project waar we moet een navigatieweergave op de startpagina toevoegen en dat omvat het bijwerken en toevoegen van verschillende bestanden. Hieronder volgt een stapsgewijze uitsplitsing van de hele stroom:

  • Je begint aan een functie met het bijwerken van een bestand ; laten we het noemen application_controller.rb
  • Voor deze functie moet je ook een weergave bijwerken: index.html.haml
  • Je hebt een deel toegevoegd dat wordt gebruikt in de indexpagina: _navigation.html.haml
  • Stijlen voor de pagina moeten ook worden bijgewerkt om het deel weer te geven dat we hebben toegevoegd: styles.css.scss
  • Feature is nu klaar met de gewenste wijzigingen, tijd om ook tests bij te werken; bestanden die moeten worden bijgewerkt, zijn als volgt:
    • application_controller_spec.rb
    • navigation_spec.rb
  • Tests worden bijgewerkt en slagen zoals verwacht, nu tijd om de wijzigingen door te voeren!

Aangezien alle bestanden tot verschillende territoria van de architectuur behoren, committeren we de veranderingen geïsoleerd van elkaar om ervoor te zorgen dat elke commit een bepaalde context vertegenwoordigt en in een bepaalde volgorde wordt gemaakt. Ik geef meestal de voorkeur aan backend – > frontend-volgorde waarbij de meeste backend-centrische wijziging eerst wordt vastgelegd, gevolgd door de middelste laag en vervolgens door frontend-centrische wijzigingen in de Git-lijst commits.

Nu we onze wijzigingen hebben vastgelegd, creëren we een samenvoegverzoek met de branch. Als je een samenvoegverzoek eenmaal hebt geopend, wordt het meestal beoordeeld door je collega voordat de wijzigingen worden samengevoegd in de repo “s master branch. Laten we nu eens kijken in welke verschillende situaties we terecht kunnen komen tijdens codereview.

Situatie 1: ik moet de meest recente commit wijzigen

Stel je een geval voor waarin de recensent keek naar styles.css.scss en stelde een verandering voor. In zon geval is het heel eenvoudig om de wijziging door te voeren, aangezien de wijzigingen in de stylesheet deel uitmaken van de laatste commit op je branch. Hier is hoe we dit kunnen aanpakken;

  • U doet direct de nodige wijzigingen aan styles.css.scss in uw branch.
  • Eenmaal je bent klaar met de wijzigingen, voeg deze wijzigingen toe aan het podium; voer git add styles.css.scss uit.
  • Zodra de wijzigingen zijn gestaged, moeten we deze wijzigingen toevoegen aan onze laatste commit; voer git commit --amend uit.
    • Commando-uitsplitsing: hier “vragen we het git commit -commando om eventuele wijzigingen aan te passen stage naar de meest recente commit.
  • Dit zal je laatste commit openen in je door Git gedefinieerde teksteditor die het vastlegbericht heeft: Stijlen toevoegen voor navigatie.
  • Aangezien we alleen de CSS-declaratie hebben bijgewerkt, hoeven we het vastlegbericht niet te wijzigen.Op dit punt kun je gewoon de teksteditor die Git voor je opende, opslaan en afsluiten en je wijzigingen zullen worden weerspiegeld in de vastlegging.

Aangezien je een bestaande vastlegging hebt gewijzigd, zijn deze wijzigingen vereist gedwongen worden gepusht naar uw externe opslagplaats met git push --force-with-lease <remote_name> <branch_name>. Dit commando zal de commit Add styles for navigation op de externe opslagplaats overschrijven met een bijgewerkte commit die we zojuist in onze lokale opslagplaats hebben gemaakt.

Een ding om in gedachten te houden bij het geforceerd pushen van branches is dat als je met meerdere mensen aan dezelfde branch werkt, force pushing problemen kan veroorzaken voor andere gebruikers wanneer ze hun wijzigingen normaal proberen te pushen op een remote branch waar nieuwe commits geforceerd gepusht zijn. Gebruik deze functie daarom verstandig. Je kunt hier meer leren over de force push-opties van Git.

Situatie 2: ik moet een specifieke commit wijzigen

In de vorige situatie was de reparatie vrij eenvoudig omdat we moesten aanpassen alleen onze laatste Git-commit, maar stel je voor dat de recensent zou voorstellen om iets te veranderen in _navigation.html.haml. In dit geval is het de tweede commit van bovenaf, dus het wijzigen ervan zal “niet zo direct zijn als in de eerste situatie. Laten we eens kijken hoe we hiermee om kunnen gaan:

Elke keer dat een commit is gemaakt in een branch, wordt het geïdentificeerd door een unieke SHA1-hash-string. Zie het als een unieke ID die de ene commit van de andere scheidt. Je kunt alle commits bekijken, samen met hun SHA1-hashes in een branch door git log uit te voeren. Hiermee zou je een output zien die er ongeveer als volgt uitziet, waarbij de meest recente commits bovenaan staan;

Dit is waar het git rebase commando in het spel komt. Elke keer dat we een specifieke commit willen bewerken met git rebase, moeten we eerst onze branch rebasen door HEAD terug te verplaatsen naar het punt net voor de commit die we willen bewerken. In ons geval moeten we de commit wijzigen die Page Navigation View leest.

Let hier op de hash van commit die vlak voor de commit staat die we willen wijzigen; kopieer de hash en voer de volgende stappen uit:

  • Rebase de branch om naar commit te verplaatsen voordat onze target commit; voer git rebase -i 8d74af102941aa0b51e1a35b8ad731284e4b5a20
    • Commando-uitsplitsing uit: hier “draaien we Git” s rebase -commando in interactieve modus met meegeleverde SHA1-hash als commit om te rebasen naar.
  • Dit zal het rebase commando voor Git in interactieve modus uitvoeren en zal je teksteditor openen met al je commits die kwamen na de commit waarnaar je gerebased hebt . Het zal er ongeveer zo uitzien:

Merk op hoe elke commit een woord heeft pick ervoor, en in de inhoud hieronder, staan alle mogelijke trefwoorden die we kunnen gebruiken. Aangezien we een vastlegging willen bewerken, moeten we pick 4155df1cdc7 Page Navigation View wijzigen in edit 4155df1cdc7 Page Navigation View. Sla de wijzigingen op en sluit de editor af.

Nu wordt je branch gerebaseed tot het punt in de tijd vlak voor de commit die je maakte, inclusief _navigation.html.haml. Open het bestand en voer de gewenste wijzigingen uit volgens de beoordelingsfeedback. Als u klaar bent met de wijzigingen, staget u ze door git add _navigation.html.haml uit te voeren.

Aangezien we de wijzigingen hebben gestaged, is het tijd om branch HEAD terug te verplaatsen naar de commit die we oorspronkelijk hadden (terwijl we ook de nieuwe wijzigingen die we hebben toegevoegd), voer git rebase --continue uit, dit zal je standaard editor openen in de terminal en je het vastlegbericht laten zien dat we tijdens rebase hebben bewerkt; Page Navigation View. Je kunt dit bericht veranderen als je wilt, maar we laten het voorlopig zoals het is, dus sla op en verlaat de editor. Op dit punt zal Git alle commits opnieuw afspelen die volgde na de commit die je zojuist hebt bewerkt en nu branch HEAD is terug naar de bovenste commit die we oorspronkelijk hadden, en het bevat ook de nieuwe wijzigingen die je hebt aangebracht in een van de commits.

Aangezien we opnieuw een commit hebben gewijzigd die “al aanwezig is in de externe repo, moeten we deze branch opnieuw forceren met git push --force-with-lease <remote_name> <branch_name>.

Situatie 3 : Ik moet commits toevoegen, verwijderen of combineren

Een veel voorkomende situatie is wanneer je verschillende commits hebt gemaakt om iets te herstellen dat je eerder hebt vastgelegd. Laten we ze nu zo veel mogelijk verminderen door ze te combineren met de originele commits.

Het enige wat je hoeft te doen is de interactieve rebase starten zoals je zou doen in de andere scenarios.

Stel je nu voor dat je al die fixes wilt combineren in c22a3fa0c5c Render navigation partial. Je hoeft alleen maar

  1. Verplaats de fixes naar boven zodat ze direct onder de commit staan die je uiteindelijk wilt behouden.
  2. Verander pick naar squash of fixup voor elk van de fixes.

Opmerking: squash behoudt de vastleggingsberichten in de beschrijving. fixup zal de vastlegberichten van de fixes vergeten en het origineel behouden.

Je “zal eindigen met zoiets als dit:

Sla de wijzigingen op, verlaat de editor , en je bent klaar! Dit is de resulterende geschiedenis:

Zoals voorheen hoef je alleen maar git push --force-with-lease <remote_name> <branch_name> en de veranderingen zijn up.

Als je de commit helemaal uit de branch wilt verwijderen, in plaats van squash of fixup, schrijf gewoon drop of verwijder gewoon die regel.

Vermijd conflicten

Om conflicten te vermijden, zorg ervoor dat u “beweegt omhoog op de tijdlijn” raakt niet dezelfde bestanden aan die zijn aangeraakt door de commits die erna zijn achtergelaten.

Pro-tip : Snelle reparaties

Als je precies weet welke commit je wilt repareren, hoef je bij het committeren geen hersencycli te verspillen met het bedenken van goede tijdelijke namen voor “Fix 1”, “Fix 2”,…, “Fix 42”.

Stap 1: Maak kennis met --fixup

Nadat je de veranderingen hebt uitgevoerd om te repareren wat het ook is dat moet worden hersteld, gewoon Git commit alle wijzigingen als volgt:

(Merk op dat dit de hash is voor de commit c22a3fa0c5c Render navigation partial)

Dit zal dit vastleggingsbericht genereren: fixup! Render navigation partial.

Stap 2: En de sidekick --autosquash

Gemakkelijke interactieve rebase. U kunt git de fixup s automatisch op de juiste plaats laten plaatsen.

git rebase -i 4155df1cdc7 --autosquash

De geschiedenis wordt als volgt weergegeven:

Klaar om gewoon herzien en verder gaan.

Als u “avontuurlijk bent ingesteld, kunt u een niet-interactieve rebase doen git rebase --autosquash, maar alleen als u graag gevaarlijk leeft, aangezien u heb geen gelegenheid om de squashs die worden gemaakt te bekijken voordat ze “opnieuw worden toegepast.

Situatie 4: Mijn Git commit-geschiedenis heeft geen zin, ik heb een nieuwe start nodig!

Als we Als we aan een grote functie werken, is het normaal dat er verschillende fixup- en review-feedbackwijzigingen zijn die regelmatig worden vastgelegd. In plaats van de branch constant opnieuw te bouwen, kunnen we het opschonen van commits uitstellen tot het einde van de ontwikkeling.

Dit is waar het maken van patchbestanden buitengewoon handig is. In feite waren patchbestanden de belangrijkste manier om code te delen via e-mail tijdens het samenwerken op grote open source-projecten voordat Git-gebaseerde services zoals GitLab beschikbaar waren voor ontwikkelaars. Stel je voor dat je zon branch hebt (bijv. add-page-navigation) waar er heel veel commits zijn die de onderliggende veranderingen niet duidelijk overbrengen. Hier is hoe je een patch-bestand voor iedereen kunt maken de wijzigingen die je in deze branch hebt aangebracht:

  • De eerste stap om het patchbestand aan te maken is ervoor te zorgen dat je branch alle wijzigingen bevat van master branch en heeft geen conflicten daarmee.
  • U kunt git rebase master of git merge master uitvoeren terwijl u “opnieuw hebt aangevinkt out in add-page-navigation branch om alle wijzigingen van master naar je branch te krijgen.
  • Maak nu het patch-bestand ; run git diff master add-page-navigation > ~/add_page_navigation.patch.
    • Commando-uitsplitsing: hier “gebruiken we Git” s diff-functie, en vragen om een diff tussen master branch en add-page-navigation branch, en het omleiden van de uitvoer (via > -symbool) naar een bestand met de naam add_page_navigation.patch in onze wij er basismap (meestal ~/ in * nix-besturingssystemen).
  • Je kunt elk pad specificeren dat je dit bestand wilt bewaren in en de bestandsnaam en extensie kan alles zijn wat je maar wilt.
  • Zodra de opdracht is uitgevoerd en je ziet geen fouten, wordt het patchbestand gegenereerd.
  • Nu uitchecken master branch; voer git checkout master uit.
  • Verwijder de branch add-page-navigation uit de lokale repo; voer git branch -D add-page-navigation uit. Onthoud dat we al wijzigingen van deze branch hebben in een aangemaakt patchbestand.
  • Maak nu een nieuwe branch aan met dezelfde naam (terwijl master is uitgecheckt); run git checkout -b add-page-navigation.
  • Op dit punt is dit een nieuwe branch en heeft “geen enkele van uw wijzigingen.
  • Ten slotte, pas toe uw wijzigingen van het patchbestand; git apply ~/add_page_navigation.patch.
  • Hier worden al uw wijzigingen toegepast in een branch en zullen ze verschijnen als niet-gecommitteerd, alsof al uw wijzigingen waar gedaan, maar geen van de wijzigingen is daadwerkelijk vastgelegd in de branch.
  • Nu kun je doorgaan en individuele bestanden of bestanden gegroepeerd op gebied van impact vastleggen in de volgorde die je wilt met beknopte vastlegberichten.

Net als bij eerdere situaties hebben we in feite de hele branch aangepast, dus het is tijd om push te forceren!

Conclusie

Hoewel we de meest voorkomende en basissituaties hebben behandeld die zich voordoen in een dagelijkse workflow met Git, is het herschrijven van Git-geschiedenis een enorm onderwerp en als je er vertrouwd mee raakt bovenstaande tips kunt u meer geavanceerde concepten over het onderwerp leren in de officiële documentatie van Git. Happy git “ing!

Foto door pan xiaozhen op Unsplash

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *