Introductie in GIT

Luuk Schimmel
Luuk Schimmel
Back-end Developer

GIT is een tool om voor code eenvoudig versies bij het houden. Het houdt van alle gemaakte wijzigingen een versie (commit) bij wanneer jij vindt dat het nodig is. Om te zorgen dat je niet telkens je collega’s in de weg zit is het mogelijk of af te takken van de standaard codebase. Dit noemen we branchen vanaf de main.



Vaak gebruik je een een aftakking (branch) voor een aparte feature. Wanneer die feature af is kan die eenvoudig teruggezet worden bij de standaard codebase. Twee branches samenvoegen wordt mergen genoemd. Soms komt het voor dat twee ontwikkelaars in verschillende branches dezelfde code hebben gewijzigd. Dit is vaak eenvoudig op te lossen wanneer niet al te veel code overlapt.   

Structuur van GIT

Om goed overweg te kunnen met GIT is het handig om te weten wat sommige termen betekenen en waar in het systeem welke versies staan.

Boomstructuur & versiebeheer

In de structuur zie je veel verschillende items. Elke node is een commit, na de tweede commit wordt er een feature gebrancht. Nadat die klaar is na twee commits wordt deze logica naar de master/main overgezet. Ook zie je de HEAD. Dit is de commit die GIT toont, dit is standaard de laatste commit die je bekijkt. Wil je een oude commit zien? Dit kan makkelijk met   $git checkout dd70cfe. Wanneer de HEAD niet automatisch naar de laatste commit van de branch verwijst, dan heb je een DETACHTED HEAD. Dan zijn de wijzigingen die daarin gedaan worden niet meer gelinkt worden aan de branch waar je in zat.

Verschillende locaties

GIT houdt 5 verschillende versies van een project bij. Dit kan heel verwarrend zijn wanneer je niet precies weet naar welke versie van je bestand je kijkt en waarom code wel op de ene plek staat, maar niet op een andere plek. Ook worden voor sommige locaties verschillende namen gebruikt.

In de afbeelding hieronder staat een overzicht van de verschillende locaties en de basic commando’s om de bestanden van de ene plek naar de andere plek te krijgen. Elke locatie heeft een eigen variatie op de boomstructuur.

Working area: de bestanden zoals ze op de computer staan.

Stash: wijzigingen de je nog even niet wilt doorvoeren

Index/staging area: welke gewijzigde documenten in de volgende commit opgenomen worden.

Local repo: De geschiedenis van alle wijzigingen op de lokale computer

Remote repo/origin: De geschiedenis van alle wijzigingen op een server (inclusief de wijzigingen van je teamgenoten)

GIT Commando’s

Het versiebeheer is heel eenvoudig, vooral wanneer je in je uppie aan een project werkt. Dit leer je spelenderwijs, daarom wordt daar niet heel diep op ingegaan. Maar wat nou wanneer ergens code staat dat (nog) niet met het publiek gedeeld mag worden? Dan komen de iets geavanceerdere opties naar boven. Omdat er met GIT veel manieren zijn voor dezelfde oplossing, worden hier een aantal van mijn favoriete commando’s en herstelstrategieën beschreven. 

Wil je alle details van alle commando’s weten, dan moet je even naar https://git-scm.com/docs.

De basics

Git hoeft niet moeilijk te zijn, vooral niet wanneer je alleen aan een project werkt. Zolang alles goed gaat kan je met de volgende commando’s alles wat nodig is.

git add . neem alle bestanden mee in de volgende commit

git commit -m [message] Leg een commit vast

git push zet de laatste commit(s) door naar de remote 

git pull haal de laatste wijzigingen van de remote

git checkout zet de pointer naar een andere branch/commit

git merge voeg een andere branch samen met de huidige

Wanneer ik het overzicht even niet meer heb dan zijn er  twee commando’s die ik vaak gebruik om overzicht te krijgen over de huidige status:

Git log --oneline Laat de laatste commits op de huidige branch zien


Git status Toont welke bestanden met de komende commit mee gaan.


Wijzigingen ongedaan maken

Binnen Infocaster maakt iedereen wel eens een foutje. Gelukkig maar, daar leren wij van. Ook zijn er natuurlijk verschillende momenten dat je realiseert dat er iets mis is gegaan. Misschien is dat tijdens het schrijven van de code, maar misschien pas wanneer iets al op de master branch staat. Hieronder zijn een aantal manieren beschreven waarbij je de fouten kan terugdraaien of zelfs helemaal verhullen.

Voorbeeld 1
Je schrijft code op de verkeerde branch.  git stash

  git checkout [juiste branch]

  git stash pop


Voorbeeld 2
Je hebt een commit gedaan, maar er mist een change of je bent niet blij met de commit message.

git add . 
git commit --amend

* Let op, hiermee wijzig je de geschiedenis
**  Wanneer het al op de origin staat heb je een force push nodig om het door te kunnen zetten.


Voorbeeld 3
Je wilt de laatste x-aantal commits ongedaan maken.

git checkout [laatste goede commit]
git checkout -b nieuwe_branchnaam


Voorbeeld 4
Je wilt de laatste x-aantal commits ongedaan maken en het maakt niet uit dat de laatste commits kwijt raken.

git reset --hard [laatste goede commit]


Voorbeeld 5
Een wijziging van 4 weken geleden wil je terugdraaien.

git revert [commit hash]

* Door dit te doen wordt er een nieuwe commit gemaakt waarbij GIT probeert de gemaakte wijzigingen terug te draaien


Geschiedenis wijzigen

Iedereen weet dat je de geschiedenis niet moet wijzigen, dat geldt ook wanneer je werkt met GIT. Er zijn een aantal hele handige commando’s, maar wanneer ze verkeerd gebruikt worden kunnen ze veel problemen opleveren. Het gaat dan voornamelijk over squash, rebase, commit --amend en filter-branch.

Deze commando’s kunnen commits samenvoegen of overschrijven, dit heeft als gevolg dat er ook commits verdwijnen. zolang je alleen je eigen geschiedenis wijzigt is er niets aan de hand. Wijzig je ook de geschiedenis van code waar andere collega’s ook vanaf gestart zijn, dan is de kans groot dat git hun code niet meer kan mergen met de originele branch.


Eigen git commando’s definiëren

Zelf ben ik een echt luie developer, hoe meer van mijn werk kan automatiseren hoe liever. Je kan heel makkelijk zelf commando’s toevoegen als je een klein beetje bash kan.  Hierdoor kan het makkelijker worden om sommige complexe commando’s te onthouden.

Zo heb ik bijvoorbeeld de volgende commando’s toegevoegd:

Custom command 1:

git find-branch git branch --list *$1*

Custom command 2:

git pushup currentBranch=$(git symbolic-ref --short -q HEAD)

git push --set-upstream origin $currentBranch

Custom command 3:

git delete-all git branch | grep -v "develop" | grep -v "main" |  xargs git branch -d


Ook kan je zorgen voor meer structuur in je commits en branches. Ik maak gebruik van regex en globale variabelen van git om een bepaalde gestructureerde naamgeving aan mijn branches en commits te geven. Door het gebruik van bash kan je veel extra checks uitvoeren en andere tools aanroepen. Zo is het bijvoorbeeld mogelijk automatisch dotnet format of resharper cleanup aanroepen voor alle gewijzigde documenten binnen de branche.