Git en GitHub
Inleiding
Versiebeheer en het doen opslaan van je broncode in een repository in de cloud? Ik loop er regelmatig tegenaan (zowel werk als privé) waarbij ik af en toe het spoor bijster ben en daarom een aantal posts over dit onderwerp om het één en ander op een rij te zetten.
We gebruiken in deze post Git als lokaal versiebeheersysteem waarbij we voor het doen opslaan van de repositories in de cloud gebruik maken van GitHub en we voor de diverse Git-commando’s gebruik maken van de Git Bash command line interface.
In deze post zullen we het voornamelijk hebben over de local repository (Git) en het doen vullen van een remote repository (GitHub) vanuit de local repository. Zaken zoals het werken met branches en het doen bijwerken van de local repository vanuit de remote repository zullen in deze post niet ter sprake komen maar in deze vervolg post.
Git, Git Bash en GitHub
Git is één van de meest gebruikte software versiebeheersystemen wereldwijd en het was ooit begonnen met Linus Torvalds in 2005. Git is (nog steeds) een open-source tool onder auspiciën van de Linux Foundation.
GitHub is een online platform voor softwareontwikkeling en versiebeheer en het host Git repositories in de cloud. GitHub Inc. is opgericht in 2008 en het werd in 2018 overgenomen door Microsoft.
Microsoft heeft naast GitHub ook haar Azure DevOps die ook repositories in de cloud host. In Microsoft’s Visual Studio worden de remote repositories van zowel GitHub als Azure DevOps ondersteund waarbij het één en ander is geïntegreerd binnen de Visual Studio IDE (maar dat valt verder buiten de scope van deze post).
De diverse Git commando’s zijn gebaseerd op een Linux omgeving en voor Windows is er de Git for Windows Git Bash (Bourne Again SHell) command line interface (CLI). Git Bash emuleert Linux en in die CLI kunnen diverse Git commando’s ingegeven worden. We gebruiken de Git Bash CLI in deze post.
Hoe mooi ze ook met elkaar geïntegreerd zijn en anders dan wat de namen zouden suggereren, Git en Github zijn twee verschillende producten. Bij die producten zijn ook nog eens twee, totaal van elkaar verschillende, partijen betrokken (de Linux Foundation voor Git en Microsoft voor GitHub).
Installatie
We gaan naar de site van Git en in de download sectie (https://git-scm.com/downloads) zien we dat meerdere besturingssystemen worden ondersteund. Git draait niet alleen op Linux/Unix, maar ook op macOS en Windows. In deze post gaan we uit van de Windows-versie.
We doen de installatie en we zien na afloop de volgende programma’s onder de Windows Start-button:
Configuratie
We starten Git Bash en we krijgen onderstaande CLI. In de Git Bash CLI gaan we naar de folder waar onze programmatuur staat (in dit voorbeeld C:\Blog\GitMRA) en we vragen de versie op van Git Bash met git –version De Git Bash CLI verlaat je met de exit-commando.
# de versie van Git Bash
git --version
# verlaat de git bash CLI met:
exit
MINGW64 staat voor ‘Minimum GNU for Windows 64 bit‘ (GNU = GNU’s Not Unix!), zijnde de compiler die gebruikt wordt voor de ‘git for Windows’ . We configureren het volgende in Git Bash:
> editor
Vanuit Git Bash wordt standaard de Vim (Visual editor IMproved)-teksteditor opgestart als we bijvoorbeeld configuratiebestanden willen bewerken. De Vim-editor met zijn ascetische jaren ’70 look-and-feel heeft niet onze voorkeur en we geven als volgt op dat we voor bewerkingen gebruik willen maken van Visual Studio Code (die dan wel aanwezig moet zijn op je PC):
git config --global core.editor "code --wait"
En we krijgen, als we het configuratiebestand met globale settings willen bewerken:
git config --global -e
Visual Studio Code te zien waarbij pas verder gegaan kan worden in de Git Bash CLI als de teksteditor is afgesloten (door de –wait-setting):
> name
Je kunt, als je met Visual Studio Code al in het configuratiebestand zit je name invullen, maar het kan ook met deze Git-commando:
git config --global user.name "<username>"
Idem dito voor het e-mail adres, maar het kan ook met deze Git-commando:
git config --global user.email "<email>"
> autocrlf
Gebruik onderstaande Git-commando voor de regeleinden als je met Windows werkt (of zet het direct in het configuratiebestand):
git config --global core.autocrlf "true"
Gebruik onderstaande Git-commando voor de regeleinden als je met Linux/Unix of macOS werkt (of zet het direct in het configuratiebestand):
git config --global core.autocrlf "input"
Locaties
De Git software versiebeheersysteem kent vier locaties en het is de bedoeling dat alle relevante bestanden alle locaties doorlopen om te eindigen in een remote repository in de cloud of weer terug te komen als een “untracked” bestand in de lokale folder op de PC:
- Allereerst is er een folder lokaal op de PC met daarin je broncode
(de desbetreffende folder is je working directory1) - Vervolgens hebben we een staging area2
(Git hanteerde voorheen de term ‘index’) - Daarna volgt de local Git repository3
(die zich nog steeds lokaal op de PC bevindt) en - Ten slotte hebben we de Remote Github repository4 in de cloud
(we gebruiken in dit voorbeeld de hosting service van GitHub)
working directory
De working directory1 is in dit voorbeeld folder C:\Blog\GitMRA met in die folder één bestand:
We maken een lokale Git repository aan met:
git init
waarna we een hidden folder .git zien zijnde de lokale Git repository. De lokale Git repository is verder nog leeg.
Het bestand in de working directory1 is nog “untracked”. Dat houdt in dat Git de wijzigingen aan dat bestand niet zal bijhouden. We zien met git status de status van het bestand:
# wat is de status?
git status
We gebruiken in het voorbeeld in deze post maar één branche, maar branches kunnen o.a. gebruikt worden in situaties waarin meerdere personen aan een software project werken en iedere ontwikkelaar zijn eigen branche heeft. De aanpassingen in die branche worden dan geëvalueerd en bij goedbevinding samengevoegd met een hoofdbranche.
Voor installaties naar bijvoorbeeld productiemachines wordt uiteindelijk de broncode gebruikt die in de hoofdbranche aanwezig is. In deze vervolgpost wordt verder ingegaan op branches.
Voorheen werd de hoofdbranche ‘master’ genoemd. De naam ‘master’ riep blijkbaar te veel associaties op met nare plantages en daarop tewerkgestelde slaven waardoor de defaultnaam voor de hoofdbranche is veranderd naar ‘main’. We gebruiken in het voorbeeld in deze post nog de oude naam ‘master’ voor de hoofdbranche.
staging area
We voeren deze Git-commando in voor het doen ’tracken’ van bestand index.html door Git:
git add index.html
(met git add . worden alle bestanden in de working directory1 ’tracked’). Met als resultaat dat het bestand wordt opgenomen in de staging area2. Als we wat aanpassen in het bestand dan merkt Git dat het bestand is gewijzigd t.o.v. wat in de staging area2 staat. We zien met git status Git’s constatering dat er verschillen zijn:
De tekst in bestand index.html is gewijzigd. In het bestand stond de tekst “De wereld is plat.” wat gewijzigd is naar “De wereld is rond.” en dat is wat we ook zien met Git-commando:
git diff
We doen weer een git add index.html zodat het gewijzigde bestand wordt toegevoegd aan de staging area2.
Dat er een staging area2 is demonstreren we als volgt door bestand index.html te verwijderen met rm index.html
Git heeft in de gaten dat een bestand is verwijderd uit de working directory1 (zie git status).
Maar geen paniek, het bestand kunnen we terughalen uit de staging area2 met git restore index.html
En het bestand is teruggehaald uit de staging area2 en weer aanwezig in de working directory1:
# voeg het bestand toe aan de staging area
git add index.html
# verwijder het bestand uit de working directory
rm index.html
# oeps.. iets is verwijderd
git status
# haal het bestand weer terug uit de staging area:
git restore index.html
(voor het doen tonen van de inhoud van de working directory1 doen we ls, de Linux-variant van wat in Ms Dos dir is)
git repository
Bestand index.html passen we weer aan. In het bestand stond de tekst “De wereld is rond.” en dat wijzigen we naar “De wereld is rond en draait om de zon.” waardoor het bestand in de working directory1 weer is gewijzigd t.o.v. wat in de staging area2 staat (zie de git diff).
We gaan vanuit de working directory1 in één keer de staging area2 en de local git repository3 üpdaten en dat doen we met deze Git-commando:
git commit -a -m "First commit to the local git repository"
Parameter -a zorgt ervoor dat het “getrackte” in de working directory1 wordt meegenomen naar de staging area2 en de local git repository3. Een git add hoef je dan niet meer te doen. Parameter -m staat voor de message die je meegeeft met de commit naar de local repository zodat je weet waar de commit betrekking op heeft:
En je krijgt met de Git-log-commando te zien wat is “gecommit” naar de local git repository3:
git log --oneline
Elke commit krijgt een unieke identifier (de getoonde waarde in oker):
github repository
Alles staat nu in de local git repository3 onder het wakend oog van Git, maar het staat nog steeds op de lokale harde schijf van je PC en alles is weg bij een computer crash.
Het is nu tijd om alles over te zetten naar een remote repository in de cloud. Met een remote repository heb je in ieder geval al iets van een backup, maar het biedt ook mogelijkheden voor het delen van je werk met anderen en het laten werken van meerdere mensen aan eenzelfde project.
We maken voor de remote repositories gebruik van de hosting services van GitHub. We creëren in GitHub een nieuwe remote repository, voor het voorbeeld in deze post:
De remote repository heeft een url die we nodig gaan hebben in Git Bash:
In Git Bash definiëren we remote verbinding origin naar de remote repository op GitHub omdat we anders vanuit Git Bash niet bij de remote repository kunnen komen. We gebruiken de url van de remote repository voor het doen maken van de remote verbinding:
# defineer remote verbinding origin:
git remote add origin https:... .git
# toon de remote verbinding:
git remote -v
En we doen een push met Git-commando git push -u origin master waardoor alles wordt overgezet van de local Git repository3 naar de Remote Github repository4 in de cloud. Het bestand wordt in die remote repository in de master branche gezet.
Parameter -u staat voor upstream en koppelt de lokale Git repository aan de Remote Github repository4 (de origin) zodat je nadien geen extra argumenten meer hoeft op te geven bij o.a. git pull en git push commando’s (meer over de pull en de push in de vervolgpost).
git push -u origin master
Er kan om een wachtwoord gevraagd worden zodra je met een push de remote repository wilt üpdaten, maar dat zal in de meeste gevallen niet gebeuren omdat het wachtwoord na een inlog op GitHub ergens lokaal op de PC wordt opgeslagen en wordt gebruikt bij o.a. push-commando’s.
Binnen Windows worden de user credentials meestal opgeslagen in de Windows Credential Manager of anders in de gebruikersdirectory in een .git-credentials-bestand. Als Git-commando git config credential.helper de waarde manager teruggeeft dan wordt de Windows Credential Manager (Control Panel > Credential Manager) gebruikt voor het doen opslaan van de user credentials.
En bestand index.html is terug te vinden in de GitHub remote repository. We vinden in het bestand de tekst “De wereld is rond en draait om de zon.” en die aangepaste tekst was ook de laatste aanpassing die hebben doorgevoerd in Git.
Git commando’s
Samenvattend de Git commando’s die we in deze post gebruikt hebben:
Configuratie
Git commando’s m.b.t. de configuratie:
# --------------#
# Configuratie
# --------------#
# om te zien welke versie van
# Git Bash is geïnstalleerd
git --version
# Stelt Visual Studio Code als
# default editor in
# parameter --wait zorgt ervoor dat
# je pas verder kunt in git bash als
# de editor is afgesloten
git config --global core.editor "code --wait"
# opent het configuratiebestand met
# een editor (de default is VIM)
# waarin de global settings staaan van Git:
git config --global -e
# user naam opgeven
git config --global user.name "<username>"
# e-mail adres opgeven
git config --global user.email "<email>"
# regeleinden instellen - Windows
git config --global core.autocrlf "true"
# regeleinden instellen - Linux/Unix/macOS
git config --global core.autocrlf "input"
Local Git repository
Git commando’s m.b.t. de local git repository3:
# ----------------------#
# Local Git repository
# ----------------------#
# Klonen uit een remote repository
# vergeet de . niet als je niet wil
# dat een extra subdirectory wordt
# aangemaakt in de folder waar je je
# kloon wilt hebben
git clone <url remote repository> .
# Local Git repository aanmaken,
# hoef je niet te doen als
# al hebt gekloond
git init
# Toevoegen van bestanden aan
# de staging area zodat ze
# gevolgd worden door Git
git add index.html
# alle bestanden in de
# working directory toevoegen
# aan de staging area
git add .
# haal het bestand weer terug
# uit de staging area
git restore index.html
# toon het verschil tussen
# de working directory en
# de staging area
git diff
# toont de status van de
# bestanden in de working dir
# zijn ze gewijzigd?
# moeten ze 'gecommit' worden?
git status
# opnemen in de local git repository
# als je parameter -a gebruikt dan
# hoef je niet eerst git add te doen
git commit -a -m "<toelichting>"
# wat is 'gecommit' naar
# de local Git repository
git log --oneline
Remote (GitHub) repository
Git commando’s m.b.t. de Remote (GitHub) repository:
#-----------------------------
# Remote github repository
#-----------------------------
# waar staan de user settings?
# als het resultaat 'manager-core'
# of 'manager' is dan staan die bij
# Windows Credential Manager
# (referentiebeheer)
git config credential.helper
# voor het doen maken van een
# remote 'origin' connectie naar
# de remote repository omdat Git
# anders niet bij de remote repository
# kan komen
git remote add origin <https:... .git>
# toont de remote verbinding:
git remote -v
# de inhoud overzetten
# van de lokale Git repository
# naar branche master in de remote repository
# parameter -u = upstream
# zodat je in het vervolg geen extra
# argumenten hoeft op te geven bij een
# git pull of git push
git push -u origin master
Locatie (fase):
a) working directory1 (unstaged)
b) staging area2 (staged)
c) local Git repository3 (committed)
d) remote (Github) repository4 (pushed)
Slot
Een hele tak van sport, maar het is de moeite waard om energie te steken in versiebeheer want je zult uiteindelijk de voordelen ervan ondervinden. Zo kunnen dingen gemakkelijker teruggedraaid worden als iets fout is gegaan omdat zowel Git als GitHub veel oude versies “onder water” bewaren en een eerdere versie altijd teruggevonden kan worden (in deze en deze posts gaan we nader in op het terughalen van een eerdere versie uit Git en GitHub).
Een remote repository biedt in ieder geval iets van een backup omdat die niet meer op de lokale harde schijf van je PC staat, maar met een remote repository kan meer. Het biedt mogelijkheden voor het doen delen van je werk met anderen en het laten werken van meerdere mensen aan eenzelfde project (in deze post gaan we in op wat te doen als meerdere mensen tegelijkertijd aan hetzelfde bestand werken en een merge conflict ontstaat).
In deze post hadden we het voornamelijk gehad over Git en het doen vullen van een GitHub remote repository vanuit Git. Zaken zoals het werken met branches en het doen bijwerken van de Local Git repository3 vanuit de Remote Github repository4 zijn in deze post niet ter sprake gekomen maar zullen in deze vervolg aan de orde komen.
Hopelijk ben je met deze posting weer wat wijzer geworden en ik hoop je weer terug te zien in één van mijn volgende blog posts. Klik op de Home-button om te zien wat ik nog meer geschreven heb…