Close

Geschiedenis herschrijven

Git commit --amend en andere methoden om geschiedenis te herschrijven


Inleiding


Deze tutorial bespreekt verschillende methoden om de Git-geschiedenis te herschrijven en te wijzigen. Git gebruikt een paar verschillende methoden om wijzigingen vast te leggen. We bespreken de sterke en zwakke punten van de verschillende methoden en geven voorbeelden van hoe je ze gebruikt. Deze tutorial bespreekt enkele van de meest voorkomende redenen voor het overschrijven van gecommitte snapshots en laat zien hoe je de valkuilen vermijdt.

De belangrijkste taak van Git is ervoor te zorgen dat je nooit een gecommitte wijziging kwijtraakt. Maar de tool is ook ontworpen om je volledige controle te bieden over je ontwikkelingsworkflow. Dit houdt in dat je precies kunt definiëren hoe je projectgeschiedenis eruitziet. Daardoor ontstaat echter ook een kans om commits te verliezen. Git biedt zijn opdrachten voor het herschrijven van geschiedenis onder het voorbehoud dat het gebruik ervan kan leiden tot verloren inhoud.

Git heeft verschillende mechanismen om geschiedenis te registreren en wijzigingen op te slaan. Deze mechanismen omvatten: Commit --amend, git rebase en git reflog. Deze opties bieden je krachtige mogelijkheden om je workflow aan te passen. Aan het einde van deze tutorial ken je de opdrachten waarmee je je Git-commits kunt herstructureren en weet je hoe je valkuilen kunt vermijden die vaak voorkomen bij het herschrijven van geschiedenis.

Git-logo
gerelateerd materiaal

Git cheat sheet

Logo Bitbucket
Oplossing bekijken

Git leren met Bitbucket Cloud

De laatste commit wijzigen: git commit --amend


De opdracht git commit --amend biedt een handige manier om de meest recente commit te wijzigen. Hiermee kun je gefaseerde wijzigingen combineren met de vorige commit in plaats van een heel nieuwe commit te maken. Hij kan ook worden gebruikt om eenvoudigweg het vorige commit-bericht te bewerken zonder het snapshot te wijzigen. Een wijziging past echter niet de meest recente commit aan, maar vervangt deze volledig. Dat betekent dat de gewijzigde commit een nieuwe entiteit zal zijn met een eigen ref. Voor Git ziet het eruit als een gloednieuwe commit, die in het onderstaande diagram wordt aangeduid met een sterretje (*). Er zijn een paar veelvoorkomende scenario's voor het gebruik van git commit --amend. In de volgende onderdelen behandelen we een aantal gebruiksvoorbeelden.

Git commitwijziging

Het meest recente Git commit-bericht wijzigen

git commit --amend

Stel dat je net een wijziging hebt gecommit en een fout hebt gemaakt in het logbericht voor je commit. Als je deze opdracht uitvoert wanneer er niets is gefaseerd, kun je het bericht van de vorige commit bewerken zonder het snapshot ervan te wijzigen.

Vroegtijdige commits vinden de hele tijd plaats tijdens je dagelijkse ontwikkeling. Het is gemakkelijk om te vergeten een bestand op te voeren of je commit-bericht een verkeerde indeling te geven De markering --amend biedt een handige manier om deze kleine fouten op te lossen.

git commit --amend -m "an updated commit message"

Door de optie -m toe te voegen, kun je vanuit de opdrachtregel een nieuw bericht doorgeven zonder dat je de editor hoeft te openen.

Bevestigde bestanden wijzigen

Het volgende voorbeeld toont een veelvoorkomend scenario in ontwikkeling op basis van Git. Laten we zeggen dat we een paar bestanden hebben bewerkt die we in één snapshot willen committen, maar vervolgens vergeten we om tijdens de eerste keer een van de bestanden toe te voegen. Je kunt de fout gewoon oplossen door het andere bestand te stagen en te committen met de markering --amend:

# Edit hello.py and main.py
git add hello.py
git commit 
# Realize you forgot to add the changes from main.py 
git add main.py 
git commit --amend --no-edit

Met de markering --no-edit kun je de wijziging in je commit aanbrengen zonder het commit-bericht te wijzigen. De resulterende commit vervangt de onvolledige en zal eruit zien alsof we de wijzigingen in hello.py en main.py in één snapshot hebben doorgevoerd.

Openbare commits niet wijzigen

Gewijzigde commits zijn eigenlijk geheel nieuwe commits, en de vorige commit zal niet langer op je huidige branch staan. Dit heeft dezelfde gevolgen als het opnieuw instellen van een openbaar snapshot. Vermijd het wijzigen van een commit waarop andere ontwikkelaars hun werk hebben gebaseerd. Dit is verwarrend voor ontwikkelaars en herstellen is ingewikkeld.

Samenvatting

Terugkijkend: met git commit --amend kun je de meest recente commit nemen en er nieuwe gestagede wijzigingen aan toevoegen. Je kunt wijzigingen toevoegen of verwijderen in het Git-staging-gedeelte en ze toepassen met een --amend-commit. Als er geen wijzigingen zijn gestaged, zal een --amend je nog steeds vragen om de laatste log van commit-berichten te wijzigen. Wees voorzichtig bij het gebruik van --amend voor commits die met andere teamleden zijn gedeeld. Het wijzigen van een commit die met een andere gebruiker wordt gedeeld, vereist mogelijk verwarrende en langdurige oplossingen voor samenvoegingsconflicten.

Oudere of meerdere commits wijzigen


Om oudere of meerdere commits te wijzigen, kun je git rebase gebruiken. Daarmee combineer je een reeks commits tot een nieuwe basiscommit. In de standaardmodus kun je met git rebase de geschiedenis letterlijk herschrijven – en automatisch commits in je huidige werkbranch toepassen op de doorgegeven branch-head. Omdat je nieuwe commits de oude zullen vervangen, is het belangrijk om git rebase niet te gebruiken op commits die openbaar zijn gepusht. Anders lijkt het erop dat je projectgeschiedenis is verdwenen.

In deze of vergelijkbare gevallen waarin het belangrijk is om een schone projectgeschiedenis te behouden, kun je de optie -i toevoegen aan git rebase om rebase interactive uit te voeren. Dit biedt je de mogelijkheid om individuele commits in het proces te veranderen in plaats van alle commits te verplaatsen. Je kunt meer te weten komen over het interactief rebasen en over aanvullende rebase-opdrachten op de git rebase-pagina.

Bevestigde bestanden wijzigen

Tijdens een rebase pauzeert de 'edit'-opdracht, ook wel e, het afspelen van de rebase op die commit en kun je aanvullende wijzigingen aanbrengen met git commit --amend. Git zal het afspelen onderbreken en een bericht tonen:

Stopped at 5d025d1... formatting
You can amend the commit now, with



 git commit --amend



Once you are satisfied with your changes, run



 git rebase --continue

Meerdere berichten

Elke reguliere Git-commit heeft een logbericht waarin wordt uitgelegd wat er in de commit is gebeurd. Deze berichten geven waardevol inzicht in de projectgeschiedenis. Je kunt tijdens een rebase een paar opdrachten uitvoeren op commits om commit-berichten te wijzigen.

Squash-commits voor een schone geschiedenis

De 'squash'-opdracht s toont het échte nut van rebase. Met squash kun je aangeven welke commits je wilt samenvoegen in de vorige commits. Dit maakt een 'schone geschiedenis' mogelijk. Tijdens het afspelen van rebase zal Git de opgegeven rebase-opdracht uitvoeren voor elke commit. In het geval van squash-commits zal Git je geconfigureerde teksteditor openen en vragen om de opgegeven commit-berichten te combineren. Dit hele proces kan als volgt worden gevisualiseerd:

Git-tutorial: voorbeeld van 'git rebase -i'

Merk op dat de commits die zijn gewijzigd met een rebase-opdracht een andere ID hebben dan de oorspronkelijke commits. Commits die zijn gemarkeerd met 'pick' hebben een nieuwe ID als de vorige commits zijn herschreven.

Moderne Git-hostingoplossingen zoals Bitbucket bieden nu 'automatische squash-functies' bij het samenvoegen. Deze functies zullen de commits van een branch automatisch rebasen en squashen wanneer je de gebruikersinterface van de gehoste oplossingen gebruikt. Raadpleeg 'Squash-commits bij het samenvoegen van een Git-branch met Bitbucket' voor meer informatie.

Samenvatting

Git rebase geeft je de mogelijkheid om je geschiedenis aan te passen en met interactieve rebasing kun je dit doen zonder een 'rommelig' spoor achter te laten. Dit creëert de vrijheid om fouten te maken en te corrigeren en je werk te verfijnen met behoud van een schone, lineaire projectgeschiedenis.

Het veiligheidsnet: git reflog


Referentielogboeken, ofwel 'reflogs', zijn een mechanisme dat Git gebruikt om updates op te nemen die zijn toegepast op tips van branches en andere commit-referenties. Met reflog kun je teruggaan naar commits –ook al wordt er niet naar verwezen door een branch of tag. Nadat de geschiedenis is herschreven, bevat de reflog informatie over de oude staat van branches en kun je zo nodig teruggaan naar die staat. Elke keer dat je branch-tip om welke reden dan ook wordt bijgewerkt (door van branches te wisselen, nieuwe wijzigingen in te voeren, geschiedenis te herschrijven of gewoon door nieuwe commits toe te voegen), wordt er een nieuwe regel toegevoegd aan de reflog. In deze sectie zullen we de opdracht git reflog op hoog niveau bekijken en enkele veelvoorkomende toepassingen verkennen.

Gebruik

git reflog

Dit toont de reflog voor de lokale repository.

git reflog --relative-date

Dit toont de reflog met relatieve datuminformatie (bijv. 2 weken geleden).

Voorbeeld

Laten we een voorbeeld bekijken om git reflog te begrijpen.

0a2e358 HEAD@{0}: reset: moving to HEAD~2
0254ea7 HEAD@{1}: checkout: moving from 2.2 to main
c10f740 HEAD@{2}: checkout: moving from main to 2.2

De reflog hierboven toont een checkout van main naar de 2.2-branch en terug. Van daaruit is er een harde reset naar een oudere commit. De laatste activiteit wordt weergegeven aan de bovenkant, met het label HEAD@{0}.

Als blijkt dat je per ongeluk terug bent gegaan, bevat de reflog de commit main die verwijst naar (0254ea7) voordat je per ongeluk 2 commits verwijderde.

git reset --hard 0254ea7

Met behulp van 'git reset' kun je nu 'main' weer terugzetten naar de eerdere commit. Dit levert een vangnet op voor het geval de geschiedenis per ongeluk werd gewijzigd.

Het is belangrijk op te merken dat de reflog alleen een vangnet biedt als er wijzigingen zijn aangebracht in je lokale repository en dat er alleen ontwikkelingen in de branch-tip van de repository's worden bijgehouden. Bovendien hebben reflog-vermeldingen een vervaldatum. De standaard vervaltijd voor reflog-items is 90 dagen.

Zie onze git reflog-pagina voor meer informatie.

Samenvatting


In dit artikel bespraken we verschillende methoden om de git-geschiedenis te veranderen en git-wijzigingen ongedaan te maken. We hebben op hoog niveau gekeken naar het git rebase-proces. Dit zijn de belangrijkste leerpunten:

  • Er zijn veel manieren om geschiedenis te herschrijven met git.
  • Gebruik git commit --amend om je laatste logbericht te wijzigen;
  • Gebruik git commit --amend om wijzigingen aan te brengen in de meest recente commit;
  • Gebruik git rebase om commits te combineren en de geschiedenis van een branch te wijzigen;
  • git rebase -i geeft veel meer gedetailleerde controle over wijzigingen in de geschiedenis dan een standaard 'git rebase'.

Lees meer over de opdrachten die we hebben behandeld op hun specifieke pagina's:


Deel dit artikel
Volgend onderwerp

Aanbevolen artikelen

Bookmark deze resources voor meer informatie over soorten DevOps-teams of voor voortdurende updates over DevOps bij Atlassian.

Mensen die samenwerken met een muur vol tools

Bitbucket-blog

Toelichting DevOps

DevOps-leertraject

Demo Den Feature-demo's met Atlassian-experts

Hoe Bitbucket Cloud werkt met Atlassian Open DevOps

Meld je aan voor onze DevOps-nieuwsbrief

Thank you for signing up