---
title:  "Git: Masterclass"
excerpt: "Ben je een ontwikkelaar of werk je als systeembeheerder in de IT? Iedereen komt tegenwoordig in contact met git. Zorg dus dat jij goed git kan!"
date:   "2023-08-23T12:00:00.000Z"
author: Eli Winderickx
hero_image: /Git_Masterclass_Cover.png
category: Git,Linux
---
## Wat is `git`?
### Waarom werken met `git`?
Git is een versiecontrole systeem uitgevonden door [Linus Torvalds](https://linuxtorvalds.com/). Hij had een betere manier nodig waarmee er samen gewerkt kon worden aan een project. Zo'n samenwerking gaat vaak heel goed tot het misloopt en dan draait het helemaal de soep in. Vooral in ontwikkeling waar ontwikkelaars elkaar zelden in het echt zien en iedereen aan eigen stukjes code werkt. Soms overlappen die aanpassingen en doen die andere wijzigingen te niet. Dergelijke conflicten kunnen met git elegant opgelost worden.

Daarnaast wordt er van alles een checksum bijgehouden. Een cryptografische berekening van ieder bestand die altijd hetzelfde moet zijn. Dit biedt als voordeel dat `git` steeds de integriteit van de bestanden kan garanderen.

Tot slot werkt `git` volledig op jouw toestel. Je kan alles op jouw toestel aanpassen, opslaan en dan "comitten". Ben jij klaar met werken of wil je een tussentijdse backup maken, kan je jouw opgeslagen wijzigingen meteen "pushen" naar een andere `repository`. Dat kan een service zijn zoals [Gitlab](https://gitlab.com) maar ook gerust een andere computer, server en dergelijke.

### Wat met tools Gitlab, Github en Bitbucket?
Deze webapplicaties werken onderliggend met `git`. Ze bieden eigenlijk een `repository` aan waar individuen, groepen of organisaties hun code op een stukje van de server beschikbaar kunnen maken aan iedereen die zij zelf kiezen. Daarrond hebben ze dan een grafische omgeving gebouwd waar je tegenwoordig ook extra features kan genieten. De meeste tools bieden ook een issue tracking aan of mijlpalen om vooruitgang in een project bij te houden. Sommige tools bieden ook tools aan om applicaties automatisch uit te rollen zodat ontwikkeling, testing en tot slot uitrol naar productie heel vlot kan gebeuren. Waar het echt gek wordt is als je een volledige Web IDE kan gebruiken om vanop ieder toestel aanpassingen te kunnen doen aan jouw code.

## De basis
### Hoe werk je met `git`?
Als `git` geïnstalleerd is op jouw toestel kan je meteen van start gaan. Anders moet je het nog even installeren. Op `RedHat`, `Fedora` en aanverwanten, kan je `git` installeren door middel van dnf (`dnf install git`). Voor Windows kan je best [een installer downloaden](https://git-scm.com/download/win) en op MacOS gebruik je best [Homebrew](https://brew.sh/) (`brew install git`).

Met `git` in jouw `PATH` na installatie (Dat gebeurt normaal automatisch), kan je een nieuwe repo starten door in de terminal naar een map te gaan en daar volgende in te typen:
```bash
git init
```

Er is nu een map aangemaakt in jouw map genaamd `.git`. Deze zal alle wijzigingen bijhouden. Verwijder deze niet en best doe je ook geen aanpassingen in deze map. Daarvoor gaan we commando's gebruiken.

`Git` werkt met branches. Standaard start je met de `master`-branch. Die naam is niet altijd interessant dus die gaan we meteen hernoemen naar iets passelijker en inclusiever; `main`

```bash
git branch -m main
```

### Configuratie
Voor we echt wijzigingen gaan doen is het goed om even stil te staan bij de configuratie. `Git` is zo'n sterke tool omdat je duidelijk kan maken wie welke wijzigingen gemaakt heeft. Dit zorgt voor een betere opvolging en kan dus ook zorgen voor een betere projectwerking. Om aan te geven wie jij bent, kan je dat meegeven aan git.

```bash
# Geef jouw Naam en e-mailadres op.
# Dit moet je maar eenmalig doen door de --global flag
git config --global user.name "Jouw Naam"
git config --global user.email "jouw@email-adr.es"
```

> Je kan jouw code ook automatisch laten `signen` met GPG. Door zo'n digitale handtekening weet iedereen zeker dat deze wijziging effectief van jou komt en niet iemand anders dat in jouw naam gedaan heeft. Dit kan je zo activeren:

```bash
# Maak een GPG-key aan als je deze nog niet hebt.
# Na onderstaand commando moet je een paar vragen beantwoorden.
gpg --gen-key
# Zoek dan de key id. Die staat op de pub regel
# achter de eerste /
gpg --list-keys
# Daarna kan je jouw key doorgeven aan git
git config --global user.signingkey <Jouw GPG-key>
# In plaats van --global kan je ook enkel voor dit project signing gebruiken
git config --local commit.gpgsign true
```

### Sla je werk op!
Nu moeten we een eerste bestand toevoegen vooraleer we echt met `git` kunnen werken. Kies hier voor een `README`-bestand. Dit wordt door `git` en vooral de `git`-tools automatisch opgepikt zodat je hier eenvoudig een korte omschrijving van jouw project kan geven. Vaak wordt hier ook instructies gelaten over hoe het project gebruikt moet worden of hoe een installatie werkt. Als we het bestand hebben aangemaakt en aangevuld, kunnen we het toevoegen aan `git` en kunnen we onze eerste `commit` maken om zo ons `git`-avontuur echt te starten. Met de `add` brengen we het bestand in de radar van `git` en met de `commit` maken we de checksum aan. Git kan nu perfect zien welke bestanden aangepast zijn. Probeer met de commit altijd kort en bondig aan te geven welke wijzigingen je gemaakt hebt door middel van de `-m` flag. Dat helpt achteraf met problemen oplossen.

```bash
# Maak eerst het bestand aan.
touch README
# Vul dat nu met gegevens dmv onze favoriete editor
# Denk eraan dat je met :wq er uit kan door op te slaan
nvim README
# Nu voegen we het bestand toe aan git.
git add README
# En tot slot een commit
git commit -m "Eerste commit met README"
```

> Als er bestanden of mappne zijn die niet opgenomen mogen worden in git, kan je die best zo vroeg mogelijk uit git houden. Dit doe je door het pad of bestandsnaam in `.gitignore` toe te voegen. Dit bestand ga je uiteraard wel toevoegen aan jouw git repo.

Het is de bedoeling dat productie gegevens steeds in de `main`-branch zullen zitten. Niemand zou rechstreeks aanpassingen hierin mogen doen buiten de initiële `commit`. In de plaats daarvan maakt iedereen een eigen branch aan. Hierin kan je dan aanpassingen doorvoeren, testen en als het goed bevonden is voeren we daarna de wijzigingen door naar de main branch. Dat gaat als volgt:
```bash
# Maak een nieuwe branch aan
git branch newfeature
# Maak een nieuw bestand aan en vul aan.
nvim myWebApp.js
# Nu voegen we het bestand toe aan git...
git add myWebApp.js
# en committen we de wijziging.
git commit -m "myWebApp.js toegevoegd"
```

### Nog enkele belangrijke bestanden
Naast het `README` bestand, zijn er nog enkele speciale bestanden waarvan je best op de hoogte bent. Niet alle projecten doen alle bestanden. Velen hebben meteen alle informatie in hun `README` staan. Hieronder vind je de meest belangrijke bestanden.
- README: De basis info van een project. Vaak ook hoe je het project kan gebruiken of in gebruik kan nemen. Online tools gaan de `Markdown` in deze bestanden automatisch tonen.
- LICENSE: Dit gaat over de rechten, ristricties en juridische fancy talk betreffende het project.
- CHANGELOG: Optioneel kan je hier in grote versienummers bijhouden welke grote veranderingen er zijn gebeurt.
- AUTHORS: De belangrijkste mensen die meewerken aan jouw project kan je hier extra in de kijker zetten. Vaak worden hier de medewerkers in loondienst ook toegevoegd.
- SUPPORT: Als iemand een issue in Gitlab of Github wilt aanmaken, kan je hier instructies meegeven over waar ze zeker rekening moeten houden alvorens hun issue in te sturen.
- SECURITY: Voornamelijk als er een kwetsbaarheid gevonden wordt, geef je hier aan hoe gebruikers dat best aan jou doorgeven. Daarnaast kan je ook versies van verschillende onderdelen hier uitschrijven.
- CODE_OF_CONDUCT: In de laatste jaren is dat vooral populair geworden. Je moet namelijk niet alleen samenwerken maar ook op een respectvolle manier. Maak in dit document duidelijk wat dat voor jouw project betekent.
- CONTRIBUTING: Als iemand nieuw wilt starten aan jouw project, vindt die hier hoe die kan helpen.
- ACKNOWLEDGEMENTS: Refereer hierin naar andere projecten die relevant zijn voor jouw project om die ook even extra in de kijker te zetten.
- CODEOWNERS: Wie heeft eigendom over de code
- FUNDING.yml: Hoe kunnen gebruikers jou financieel steunen
- ISSUE_TEMPLATE: Een template om een issue aan te maken.
- PULL_REQUEST_TEMPLATE: Een template om een `merge` aan te vragen

### Hoe krijg ik mijn project nu gedeeld?
Als je een project aanmaakt in een online tool zoals Gitlab of Github, krijg je de vraag om ook het project te initialiseren. Doe dat enkel als je nog geen lokaal project hebt. Anders hou je het project best leeg. Hierna ga je ongetwijfeld ook de instructies van die site krijgen over hoe je jouw wijzigingen online krijgt. In grote lijnen is dat meestal zo:
```bash
# Je gaat de externe locatie definiëren
git remote add origin git@gitlab.com:eliwinderickx/backuptest.git
# Bij iedere eerste push per branch ga je misschien
# moeten meegeven naar waar de push moet gebeuren
git push --set-upstream origin main
# Daarna kan je na iedere commit een push doen
# om de commit ook online beschikbaar te maken.
git push
```

### Wat ben ik nu aan het doen?
Je kan op ieder moment de status opvragen om zo te zien welke bestanden je hebt toegevoegd aan `git`, welke je hebt aangepast of misschien zelfs verwijderd. Als je `commit` hebt, kan je ook zien dat je op een propere branch aan het werken bent. Dat wil zeggen dat binnen jouw lokale `git`-repo alles veilig opgeslagen is.

> Commit wilt niet zeggen dat je wijzigingen opgeslagen zijn in een externe `git`-repo zoals Gitlab of Github.

De status vraag je zo op:
```bash
git status
```

Naast de status van de huidige branch, kan je ook een oplijsting vragen van alle branches die je lokaal beschikbaar hebt.
```bash
git branch --list
# Wil je dat visueler zien met welke branch van waar komt?
git log --all --graph --decorate --oneline --simplify-by-decoration
```

![Voorbeeld van een branch graph](/GitBranchGraph.png)

> Nog een leuke feature is zien wie de laatste commits in een bestand gedaan heeft `git blame <bestand>`


### Ik ben klaar, wat nu?
Stel de feature waaraan je gewerkt hebt is klaar. Je hebt een hele reeks nieuwe aanpassingen gemaakt, alles is getest en nu wil je jouw wijzigingen naar productie brengen. Dat doe je door die wijzigingen naar de hoofd branch te brengen. In ons verhaal hierboven hebben we die `main` genoemd. Om die wijzigingen nu naar de `main`-branch te krijgen moeten we een `merge` doen. In tools zoals Github of Gitlab kunnen we een `merge request` maken. Dit nodigd dan andere gebruikers uit om de nieuwe wijzigingen te controleren en zelf ook uit te testen alvorens dit naar de productie branch gaat. Binnen de `git`-applicatie kunnen we ook verscheidene soorten `merge`'s doen. Hier houden we het voorlopig nog even simpel.

```bash
# Eerst gaan we naar de branch die de wijzigingen moet ontvangen
git checkout main
# Daarna kunnen we de wijzigingen binnenhalen.
git merge newfeature
```

De wijzigingen zitten nu zowel in de `main` als in de `newfeature` branch. Afhankelijk van hoe je met het project omgaat, ga je misschien nu de `newfeature` branch willen verwijderen. In sommige projecten moet er per unieke feature een aparte branch gemaakt worden. Deze wordt dan na succesvol toevoegen van die feature verwijderd. Grotere projecten kunnen ervoor kiezen om onder de `main` branch ook nog type wijzigingen als branch te vertegenwoordigen; Taal, GUI en gelijkaardige grotere branches zullen niet verwijderd worden na de merge. Hierbinnen wordt verder gewerkt aan de volgende features.

```bash
# Om een branch te verwijderen, kan je zo doen
git branch -d newFeature
```

## Samenwerken is niet zonder problemen
### Iemand anders brengt wijzigingen naar productie
Jij bent nog aan het werken aan features in jouw eigen branch maar ondertussen heeft iemand anders al wijzigingen gemerged met de `main` branch. Om problemen te vermijden, kan je nu best een `rebase` doen. Dit vertaalt bij letterlijk naar vervang de basis van waar ik gestart ben door wat er in een andere branch zit. Daarbovenop kunnen we dan onze wijzigingen doen.

> Als je hier wilt meevolgen, maak dan even een nieuwe branch aangenaamt `newFeature2`. Daarna kan je in jouw `main`-branch een nieuw bestand aanmaken en een commit uitvoeren.

```bash
# Ga naar de branch die de wijzigingen moet ontvangen
git checkout newFeature2
# Hier ontvangen we de nieuwe basis vanuit main
git rebase main
```

> Bovenstaande lukt enkel als de wijzigingen in andere bestanden gebeuren. Als je dezelfde bestanden wijzigd, kom je in het vaarwater van de `stash` en het `merge conflict`.

### De `stash`
Wil je een rebase doen maar ben je indezelfde bestanden aan het werken? Dan kan je een `stash` doen. Hiermee zet je jouw wijzigingen even aan de kant om de nieuwe code of wijzigingen binnen te halen. Als dat gedaan is kan je jouw wijzigingen terughalen.

```bash
# zet jouw wijzigingen even aan de kant.
# Je draait zo even alle wijzigingen terug tot de laatste commit
git stash
# Nu kan je de rebase doen
git rebase main
# Tot slot kan je jouw wijzigingen uit stash halen
# en opnieuw uitvoeren
git stash apply
```
![git stash, rebase en dan een stash apply](/GitStashRebase.png)

### Het merge conflict
Als je bestanden aan het wijzigen was die achter jouw rug ook al gewijzigd waren, krijg je een merge conflict. `Git` kan namelijk niet in jouw plaats kiezen welke wijziging belangrijker is dan de andere. Jij gaat nu die keuze moeten maken om dit op te lossen. Voortbouwend op het scenario bij `stash` hebben we net onze stash opnieuw toegepast. We waren helaas aanpassingen aan het doen in een bestand dat in een eerdere merge in de `main` branch ook al wijzigingen kreeg. We hebben nu een `merge conflict`. Dit merken we door twee zaken:
- de output van ons laatste commando geeft het ons mee: `CONFLICT (content): Merge conflict in <bestandsnaam>` alsook
- in het bestand zelf. Hieronder een voorbeeld van hoe zo'n bestand eruit kan zien.

```
Oorspronkelijke code
<Iemand anders wijzigingen>
<Jouw wijzigingen>
```

![Voorbeeld van een git merge conflict](/GitMergeConflict.png)



De gemakkelijkste manier van werken is nu beide blokken code lezen:
- vanaf <<<<<<< tot =======
- vanaf ======= tot >>>>>>>

Hierna kan je dan beide blokken vervangen door één blok die ofwel beide codes zal bevatten of misschien bepaalde stukken zal aanpassen. Dit zal afhangen van zowel de code die er stond alsook de code die jij aan het schrijven was.

![Een mogelijke oplossing voor het merge conflict](/GitConflictSolved.png)

Achteraf moet je het bestand opnieuw toevoegen aan git en kan je een commit uitvoeren om de merge helemaal rond te krijgen.
```bash
git add <conflictbestand>
git commit -m "Conflict opgelost!"
```

## Proficiat!
![Gif van Champagne wordt ontkurkt](/champagne.gif)
Als je goed meegevolgd hebt, snap je nu hoe git werkt. Er zijn nog scenario's die we niet overlopen hebben. Die komen vaak minder voor maar kan je zeker wel terugvinden in [de officiele Git documentatie](https://git-scm.com/docs/). Lees die dus zeker na voor je problemen hebt!
