Ga naar inhoud

Git CLI en Theoretische Fundamenten

NOTES

  • Alles is LOKAAL
  • .git, niet echt leeg
  • Lifecycle, terugkomen op diagram na elke stap
    • add (staging area = beetje zoals winkelkar voor je naar de kassa gaat), commit, staging area terug leeg, rm, log
  • Undo
  • Diffs
  • Oefening
  • Config

Er zijn oefeningen. Je hoeft dus niet mee te doen als ik iets toon.

Versiebeheer en Git zijn cruciaal als professioneel maar ook hobby dev. Maar ook: centraal en onmisbaar bij gebruik van AI.

GitOps: https://chrisshort.net/gitops-an-implementation-of-devops/

We hebben GitHub (de web-interface) en GitHub Desktop gebruikt om een Git repo aan te maken, wijzigingen op te slaan (commit), de repo lokaal te krijgen (clone) en lokale aanpassingen naar GitHub door te sturen (push).

In dit hoofdstuk zetten we eerst een stapje terug door met de Git CLI (Command Line Interface) te leren werken. We doen dit initieel volledig lokaal. We leren de basisconcepten van Git zelf en commando's die je dagelijks gebruikt.

Fundamenten

Met een CLI leren werken terwijl er grafische Git-clients zoals GitHub Desktop bestaan, lijkt misschien overbodig of zinloos...

De CLI is echter een uitstekende manier om een fundamentele kennis van Git op te bouwen. Met een goed inzicht in die fundamenten zullen meer geavanceerde concepten die later aan bod komen veel gemakkelijker te begrijpen zijn.

De CLI:

  • Is altijd en overal bruikbaar
  • Werkt precies hetzelfde op elk platform
  • Helpt je de fundamenten te begrijpen
  • Wordt veel gebruikt door AI Agents

Git CLI Installeren

Download en installeer de laatste versie vanaf https://git-scm.com/downloads/win.

Als je Windows Subsystem for Linux (WSL) gebruikt, volg dan de Linux instructies. Je kan ook beide versies installeren.

Git installeren op macOS is het makkelijkst via Homebrew, een pakketbeheersysteem waarmee je eenvoudig heel wat extra software kan installeren.

Op de Homebrew homepage vind je een link naar "Homebrew's laatste GitHub release". Daar kan je onderaan de pagina Homebrew downloaden (bvb. Homebrew-4.6.11.pkg).

Eens Homebrew geïnstalleerd is kan je Git als volgt installeren vanuit een Terminal sessie:

brew install git

Meer info: https://git-scm.com/downloads/mac

Vanuit een terminal sessie:

sudo apt-get install git

Of:

sudo dnf install git

Meer info: https://git-scm.com/downloads/linux

Testen

Vanuit een terminal (Cmd of Powershell voor Windows):

git --versiongit version 2.55.0

Dit werkt ook in een terminal die je rechtstreeks in VS Code opent (View → Terminal of CTRL+`/CMD+`).

Documentatie

De Git documentatie is erg goed en een handige bron om bij de hand te hebben.

git help

git help -a

git help commit

Het uitstekende boek Pro Git is gratis beschikbaar, zowel online als in PDF of ePub formaat.

Basis Configuratie

We komen later terug op configuratiemogelijkheden van Git. Om verder te werken is het belangrijk eerst een aantal basisinstellingen aan te passen. Gebruik in onderstaande commando's je eigen naam en email adres.

git config --global user.name "John Doe"

git config --global user.email "john.doe@gmail.com"

git config --global init.defaultBranch main

Wat een defaultBranch precies is en waarom we dit aanpassen komt ook later nog aan bod.

Git Repository

NOTES

Duidelijk en uitgebreid uitleggen wat er precies gebeurd.

  • We gaan een LOKAAL Git systeem opzetten om de versies te beheren van een fictief project
  • Git bewaart alle informatie over de versies in een soort database
  • Met git init maken we zo een nieuwe (lege) database voor ons project
  • directory = folder = repo = programmeer-project
  • staging = winkelkar

Repository

Een Git repository, of kortweg repo, is een opslagplaats die de complete geschiedenis en huidige staat van een codebase (project) bewaart, inclusief bestanden, wijzigingen en versies.

Één directory (folder of map) = één git repo

Je kan van elke directory een Git repo maken. Die directory hoeft niet leeg te zijn.

In VS Code maken we een nieuwe directory om in te werken. In het startscherm kies je Open..., ofwel File → Open in het menu (= CTRL+O / CMD+O). Maak een nieuwe directory met een naam naar keuze (bvb. hello) en open deze.

In VS Code voeg je dan volgende bestanden toe:

README.md
# My first Git repo
hello.py
print("Hello from Git")

Repository Aanmaken - init

Om de Git CLI te gebruiken hebben we een terminal nodig. Dit kan via een aparte applicatie (Terminal applicatie in Linux/macOS; WSL, Cmd of Powershell in Windows). Maar je kan ook rechtstreeks in VS Code een terminal openen via View → Terminal (of CTRL+` / CMD+`).

Om een Git repo te maken (initialiseren) gebruik je het commando git init (in de directory):

git init
Initialized empty Git repository in /Users/syntra/dev/hello/.git/

Het commando git status geeft informatie over de repo en zullen we nog veel gebruiken:

git statusOn branch main

No commits yet

Untracked files: # (1)
(use "git add <file>..." to include in what will be committed)
README.md
hello.py

nothing added to commit but untracked files present (use "git add" to track)

In de output zie je dat we op de branch (tak, zoals de tak van een boom) genaamd main zitten. Een branch kan je zien als één bepaalde lijst met versies (commits) van de code. Om te beginnen zal dit altijd main zijn. Wat een branch precies is, en hoe je er mee werkt, komt later nog uitgebreid aan bod.

Extra: De .git directory

In de output van git init zie je dat een .git directory is gemaakt.

Alle git informatie zal worden bijgehouden in deze directory (en enkel deze directory). Dit betekent dat:

  • Je zelf zeker geen wijzigingen in deze directory mag maken!
  • Na het verwijderen van deze directory zijn alle sporen van git weg.

rm -rf .gitgit statusfatal: not a git repository (or any of the parent directories): .git

https://wizardzines.com/comics/inside-git/

Lifecycle van een Bestand

NOTES

Superbelangrijk en gaan we nog veel op terugkomen!

Terugkomen op diagram bij elk commando in de volgende secties.

In Git bevindt elk bestand zich altijd in één bepaalde state (staat, of status). Via de verschillende commando's kan die state veranderen.

Elk bestand begint in de untracked state. Dit zien we duidelijk in de output van het git status commando. Dit betekent dat het bestand nog onbekend is voor Git.

Eenmaal een bestand gekend is zal het altijd in één van de drie mogelijke states verkeren: modified, staged of committed

git add

Om een nieuw bestand toe te voegen aan de Git repo gebruik je eerst het commando git add. De state van het bestand verandert dan naar staged. Het bestand zit dan in de zogenoemde staging area. In de staging area verzamel je een groep bestanden en wijzigingen die als één transactie toegevoegd zullen worden in het versie-systeem. Het is dus een soort wachtplaats.

git add hello.pygit statusOn branch main

No commits yet

Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: hello.py

Untracked files:
(use "git add <file>..." to include in what will be committed)
README.md

In GitHub Desktop deden we dit door bestanden aan of af te vinken.

git commit

Nadat de gewenste bestanden en wijzigingen zijn klaargezet in de staging area kunnen ze als één geheel worden toegevoegd aan de Git-history met het commando git commit. Met het argument -m/--message geef je een beschrijving van de wijzigingen.

git commit -m "Add initial hello.py version"[main (root-commit) f39a6cc] Add initial hello.py version
1 file changed, 1 insertion(+)
create mode 100644 hello.py

git statusOn branch main
nothing to commit, working tree clean

git status vertelt ons hier dat de working tree clean is. De working tree (of working directory) is de verzameling bestanden die overeenkomt met de huidige branch (of commit). M.a.w. de bestanden die je op dat moment in de directory van je repo kan zien en gebruiken. De working tree is "clean" wanneer er geen veranderingen zijn t.o.v. de gecommitte versie.

'The Staging Area', Julia Evans

Julia Evans maakt al meer dan 10 jaar bijzonder leerzame blog-posts en samenvattingen in strip-formaat over allerlei technologische onderwerpen. Ook Git komt vaak aan bod, zoals hier:

https://wizardzines.com/comics/the-staging-area/

Oefening

Maak een kleine aanpassing in hello.py. Gebruik git status om te bevestigen dat de state van hello.py nu modified is.

Stage deze aanpassing alsook het README.md bestand. Commit dan de aanpassingen. Controleer het resultaat met git status

Oplossing

Maak een aanpassing in hello.py met je editor. Bvb.

hello.py
message = "Hello from my first Git repo"
print(message)

git statusOn branch main
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: hello.py

Untracked files:
(use "git add <file>..." to include in what will be committed)
README.md

no changes added to commit (use "git add" and/or "git commit -a")
git add hello.py README.mdgit commit -m "Improve hello.py and add README"[main 245bfa1] Improve hello.py and add README
2 files changed, 3 insertions(+), 1 deletion(-)
create mode 100644 README.md
git statusOn branch main
nothing to commit, working tree clean

git rm

Het kan gebeuren dat een bestand per ongeluk in de Git-history is beland. Of gewoon niet meer nodig is. Om een bestand uit Git te verwijderen gebruik je het git rm commando.

Let op!

Met git rm wordt het bestand uit Git en je computer verwijderd. Om enkel uit Git te verwijderen gebruik je het --cached argument. Het bestand blijft dan gewoon bestaan en is terug in de untracked state.

git rm --cached README.mdgit statusOn branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
deleted: README.md

Untracked files:
(use "git add <file>..." to include in what will be committed)
README.md

Net als bij git add wordt het te verwijderen bestand eerst toegevoegd aan de staging area. Om de verwijdering (samen met eventuele andere aanpassingen) effectief door te voeren gebruiken we opnieuw git commit

git commit -m "Remove README"[main 80b00ac] Remove README
1 file changed, 1 deletion(-)
delete mode 100644 README.md

Commit Geschiedenis (History)

Elke commit bevat de volgende informatie:

  • ID
  • Auteur (wie)
  • Datum (wanneer)
  • Beschrijving (waarom)
  • Diff (wat)

git log

Met het git log commando kan je de commit geschiedenis bekijken, vanaf de laatste commit. Met het commando git help log zie je dat er erg veel opties en mogelijkheden zijn. We bekijken hier de meest gebruikte.

git logcommit 3ecf8d528d7a591210c53e93a5f87787284103fd (HEAD -> main)
Author: Fabrice Devaux <fabrice.devaux@gmail.com>
Date: Sun Aug 24 14:56:26 2025 +0200

Improve hello.py and add README

commit f39a6cce08ebbb1a63616030322e46b4ff4d653c
Author: Fabrice Devaux <fabrice.devaux@gmail.com>
Date: Sun Aug 24 14:31:08 2025 +0200

Add initial hello.py version

(HEAD is een reference en main is een branch - hier komen we later op terug)

'The current branch: HEAD', Julia Evans

https://wizardzines.com/comics/the-current-branch-head/

--oneline optie

Met git log --oneline krijg je, zoals te verwachten, een enkele lijn per commit.

git log --oneline3ecf8d5 (HEAD -> main) Improve hello.py and add README
f39a6cc Add initial hello.py version

Je ziet dat de commit ID ingekort is tot de eerste 7 karakters. Dit is hier genoeg om een unieke commit aan te duiden.

--stat optie

Met git log --stat krijg je voor elke commit de "statistieken" van de wijzigingen: welke bestanden, hoeveel lijnen en het soort wijziging.

Je kan de opties vaak ook combineren. Zo zal git log --oneline --stat de commit informatie op 1 lijn plaatsen, gevolgd door de statistieken.

git log --oneline --stat3ecf8d5 (HEAD -> main) Improve hello.py and add README
README.md | 1 +
hello.py | 3 ++-
2 files changed, 3 insertions(+), 1 deletion(-)
f39a6cc Add initial hello.py version
hello.py | 1 +
1 file changed, 1 insertion(+)

filename argument

Door na het git log commando een bestandsnaam te plaatsen krijgen we enkel de commits te zien die betrekking hebben op dat bestand.

git log --oneline README.md3ecf8d5 (HEAD -> main) Improve hello.py and add README

Veranderingen ongedaan maken

git restore

Met git restore kan je veranderingen die nog niet gestaged zijn ongedaan maken. In het lifecycle diagram: van modified naar committed.

Merk op dat de output van git status je het juiste commando al aangeeft.

Na een ongewenste verandering in hello.py:

git statusOn branch main
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: hello.py

no changes added to commit (use "git add" and/or "git commit -a")
git restore hello.pygit statusOn branch main
nothing to commit, working tree clean

Let op!

git restore is permanent. De veranderingen zijn nooit toegevoegd in de Git geschiedenis dus kunnen ook niet terug opgehaald worden.

Als het bestand geopend is in een editor zoals VS Code kan je mogelijks wel nog de veranderingen terug krijgen.

Unstage (git restore --staged)

Met git restore --staged kan je veranderingen die wel al gestaged zijn ongedaan maken. In het lifecycle diagram: van staged naar modified.

Opnieuw krijg je van git status het geschikte commando.

Na een ongewenste verandering in hello.py:

git add hello.pygit statusOn branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: hello.py
git restore --staged hello.pygit statusOn branch main
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: hello.py

no changes added to commit (use "git add" and/or "git commit -a")
git restore hello.py

NOTES

Later bekijken we hoe je ook reeds gecommitte veranderingen ongedaan kan maken.

Veranderingen Bekijken

Git houdt alle versies en details superefficient bij. Het is dan ook belangrijk om snel en gemakkelijk specifieke versies en verschillen te kunnen ophalen.

Een diff is een weergave van de verschillen tussen twee versies van een of meerdere bestand(en), waarbij zichtbaar wordt welke regels zijn toegevoegd, gewijzigd of verwijderd. Een diff is niet specifiek aan Git -- zo zal het Linux commando diff a.txt b.txt de verschillen weergeven tussen de bestanden a.txt en b.txt.

Nieuwe wijzigingen

Wijzigingen die nog niet gestaged zijn bekijk je met het git diff commando.

Na het toevoegen van een regel in README.md:

git diffdiff --git a/README.md b/README.md
index 3836229..9ebb1b9 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,2 @@
# My first Git repo
+This is a new line

Let op!

git diff toont alleen wijzigingen in bestanden die al getrackt worden (gekend zijn) door Git. Een nieuw bestand zal je dus niet te zien krijgen!

Om de wijzigingen die wel al gestaged zijn te zien gebruik je het git diff --staged commando.

git add README.mdgit diff --stageddiff --git a/README.md b/README.md
index 3836229..9ebb1b9 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,2 @@
# My first Git repo
+This is a new line

Bestaande Commits en Diffs

Om de inhoud van een bestaande commit te bekijken is er het commando git show.

git show 3ecf8d5commit 3ecf8d528d7a591210c53e93a5f87787284103fd (HEAD -> main)
Author: Fabrice Devaux <fabrice.devaux@gmail.com>
Date: Sun Aug 24 14:56:26 2025 +0200

Improve hello.py and add README

diff --git a/README.md b/README.md
new file mode 100644
index 0000000..3836229
--- /dev/null
+++ b/README.md
@@ -0,0 +1 @@
+# My first Git repo
diff --git a/hello.py b/hello.py
index 078d6bf..e0f8470 100644
--- a/hello.py
+++ b/hello.py
@@ -1 +1,2 @@
-print("Hello Git")
+message = "Hello from my first Git repo"
+print(message)

Met git log -p (-p voor patch) krijgen we dezelfde informatie voor een lijst commits.

git log -pcommit 3ecf8d528d7a591210c53e93a5f87787284103fd
Author: Fabrice Devaux <fabrice.devaux@gmail.com>
Date: Sun Aug 24 14:56:26 2025 +0200

Improve hello.py and add README

diff --git a/README.md b/README.md
...

commit f39a6cce08ebbb1a63616030322e46b4ff4d653c
Author: Fabrice Devaux <fabrice.devaux@gmail.com>
Date: Sun Aug 24 14:31:08 2025 +0200

Add initial hello.py version

diff --git a/hello.py b/hello.py
new file mode 100644
...

Met git diff kunnen we ook een diff krijgen met alle wijzigingen tussen twee specifieke commits.

git diff f39a6cc..3ecf8d5 geeft alle verschillende tussen de commits f39a6cc en 3ecf8d5.

Git Blame

git blame (letterlijk beschuldigen) is een superhandig commando waarmee je lijn per lijn precies kan zien wie als laatste die lijn heeft aangepast, wat de commit ID is, en wanneer dit gebeurd is.

git blame hello.py455cc537 (Fabrice Devaux 2025-09-07 09:30:14 +0200 1) """Module to print a welcome message"""
455cc537 (Fabrice Devaux 2025-09-07 09:30:14 +0200 2)
3ecf8d52 (Fabrice Devaux 2025-08-24 14:56:26 +0200 3) message = "Hello from my first Git repo"
3ecf8d52 (Fabrice Devaux 2025-08-24 14:56:26 +0200 4) print(message)

Ons klein test-projectje bevat natuurlijk niet veel veranderingen. Wil je een idee krijgen van de kracht van dit commando, bekijk dan eens een grotere codebase zoals FastAPI: https://github.com/fastapi/fastapi/blame/master/fastapi/openapi/models.py.

Oefeningen

  1. Voeg een nieuw bestand test.py toe (commit)
  2. Pas iets aan in README.md en test.py
  3. Stage de aanpassingen in README.md
  4. Bekijk de commit geschiedenis en status van de repo
  5. Bekijk de uitstaande aanpassingen
  6. Maak alle uitstaande aanpassingen ongedaan. Gebruik enkel git commando's.
  7. Verwijder het test.py bestand en commit deze verandering
Extra: Aanpassingen in een staged bestand

Wat gebeurt er als een bestand dat al gestaged is (maar nog niet gecommit) wordt gewijzigd?

echo '# Test' >> hello.pygit statusOn branch main

No commits yet

Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: hello.py

Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: hello.py

Het hello.py bestand is nu gestaged en niet gestaged tegelijk! Wanneer een bestand wordt gestaged houdt Git de exacte versie van het bestand bij op dat moment. M.a.w. de oorspronkelijke inhoud van het bestand is nog steeds gestaged, maar de latere aanpassing niet. We zouden nu enkel de oorspronkelijke versie kunnen committen, of de nieuwe aanpassingen ook stagen (opnieuw met git add hello.py).

Configuratie

git config

Git heeft een heleboel configuratieparameters. De meesten zul je echter nooit moeten aanpassen.

De configuratie wordt bewaard in gewone tekst-bestanden en kan op 3 locaties voorkomen. Elke locatie overschrijft de waarden van de vorige.

Die bestanden pas je in principe niet met de hand aan. Met het git config commando kunnen we configuratie bekijken en aanpassen.

Bestand Toepassing Git commando
/etc/gitconfig
(C:\ProgramData\Git\config op Windows)
Iedere gebruiker git config --system
~/.gitconfig of ~/.config/git/config
(C:\Users\$USER\.gitconfig op Windows)
Huidige gebruiker git config --global
<repo-directory>/.git/config Lokale repo git config

Met git help -c krijg je een lijst van alle mogelijke parameters. Om te beginnen zijn er maar een paar die we willen aanpassen.

Identiteit

De user.name en user.email parameters worden gebruikt in commits. Hier willen we onze eigen identiteit instellen - zeker in repos waar we onze code willen delen, of waar we zullen samenwerken met andere ontwikkelaars.

Omdat dit in principe hetzelfde zal zijn voor elke repo gebruiken we --global. Met git config get kunnen we de waarde van een parameter controleren.

git config --global user.name "Fabrice Devaux"git config --global user.email "fabrice.devaux@gmail.com"git config get user.nameFabrice Devaux

Editor

Soms heeft een Git commando tekst input nodig van de gebruiker. Bijvoorbeeld bij het git commit commando wanneer geen commit message is meegegeven met de -m parameter. Git zal dan je tekst editor openen zodat je daar een commit message kan samenstellen.

Op Linux, macOS en WSL zal dit standaard de waarde van de $EDITOR variabele zijn (meestal vim of emacs). Als je met vim kan werken is dat een goede optie. Met de core.editor configuratie parameter kunnen we Git een andere editor laten gebruiken.

Bijvoorbeeld om VS Code te gebruiken op Linux, macOS of Windows:

git config --global core.editor "code --wait"

Configuratie overzicht

Met git config --list --show-origin krijg je een overzicht van alle aangepaste configuratie en waar die configuratie ingesteld is.

git config --list --show-originfile:/Users/dfabrice/.gitconfig core.editor=code --wait
file:/Users/dfabrice/.gitconfig user.email=fabrice.devaux@gmail.com
file:/Users/dfabrice/.gitconfig user.name=Fabrice Devaux

Bestanden negeren (.gitignore)

Er zullen altijd een aantal bestanden of directories zijn die je nooit wilt committen. Je kan Git configureren om deze altijd te negeren m.b.v. het .gitignore bestand. Hierin plaats je telkens op een aparte lijn de naam of een expressie van wat genegeerd moet worden.

Het .gitignore bestand zelf voeg je wel toe in Git.

.gitignore
__pycache__/
.vscode/
*.temp
git add .gitignoregit commit -m "Add .gitignore"[main c758209] Add .gitignore
1 file changed, 3 insertions(+)
create mode 100644 .gitignore
touch test.tempgit statusOn branch main
nothing to commit, working tree clean

Samenvatting

Samenvatting

  • De Git CLI is altijd en overal bruikbaar en werkt hetzelfde op elk platform. Ze bouwt fundamenteel inzicht op in Git en wordt veel gebruikt door AI Agents.
  • De basisconfiguratie doe je met git config --global: user.name, user.email en init.defaultBranch.

  • Eén directory = één repo: met git init maak je van elke directory een repo. Alle Git-informatie leeft in de verborgen .git directory.
  • Elk bestand zit in één state: untracked, modified, staged of committed (het lifecycle diagram!). Met git add zet je bestanden klaar in de staging area, een wachtplaats; met git commit gaan ze als één geheel de geschiedenis in. git rm verwijdert een bestand uit Git - met --cached blijft het bestand bestaan.
  • git status toont de state van de repo en geeft ook telkens het juiste commando aan.

  • Elke commit bevat ID, auteur, datum, beschrijving en diff. Met git log bekijk je de geschiedenis - met --oneline, --stat of een bestandsnaam als argument.
  • Wijzigingen ongedaan maken kan met git restore (modified → committed - permanent!) en git restore --staged (staged → modified).
  • git diff toont niet-gestagde wijzigingen (enkel van bestanden die Git al kent!), git diff --staged de gestagde. git show en git log -p tonen de diffs van commits, git diff <a>..<b> vergelijkt twee commits. git blame toont per lijn wie, wanneer en in welke commit iets veranderde.

  • De configuratie wordt bewaard in 3 locaties (--system, --global en lokaal); elke locatie overschrijft de vorige. Met core.editor kies je de editor die Git opent. git config --list --show-origin geeft een overzicht van de aangepaste configuratie.
  • Het bestand .gitignore zorgt dat bestanden die je nooit wil committen ook nooit gecommit worden. Het .gitignore bestand zelf voeg je wel toe aan Git.

Wat moet je kunnen?

  • Je kent het lifecycle diagram grondig!

  • Je kan de output van een git status commando interpreteren
  • Je kan met git add en git commit werken om nieuwe aanpassingen te committen
  • Je begrijpt de output van het git log commando
  • Je weet het je met git show een bepaalde commit kan inspecteren en begrijpt de output

  • Je weet wat het .gitignore bestand doet