-
1. Aan de slag
- 1.1 Over versiebeheer
- 1.2 Een kort historisch overzicht van Git
- 1.3 Wat is Git?
- 1.4 De commando-regel
- 1.5 Git installeren
- 1.6 Git klaarmaken voor eerste gebruik
- 1.7 Hulp krijgen
- 1.8 Samenvatting
-
2. Git Basics
-
3. Branchen in Git
- 3.1 Branches in vogelvlucht
- 3.2 Eenvoudig branchen en mergen
- 3.3 Branch-beheer
- 3.4 Branch workflows
- 3.5 Branches op afstand (Remote branches)
- 3.6 Rebasen
- 3.7 Samenvatting
-
4. Git op de server
- 4.1 De protocollen
- 4.2 Git op een server krijgen
- 4.3 Je publieke SSH sleutel genereren
- 4.4 De server opzetten
- 4.5 Git Daemon
- 4.6 Slimme HTTP
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 Hosting oplossingen van derden
- 4.10 Samenvatting
-
5. Gedistribueerd Git
-
6. GitHub
-
7. Git Tools
- 7.1 Revisie Selectie
- 7.2 Interactief stagen
- 7.3 Stashen en opschonen
- 7.4 Je werk tekenen
- 7.5 Zoeken
- 7.6 Geschiedenis herschrijven
- 7.7 Reset ontrafeld
- 7.8 Mergen voor gevorderden
- 7.9 Rerere
- 7.10 Debuggen met Git
- 7.11 Submodules
- 7.12 Bundelen
- 7.13 Vervangen
- 7.14 Het opslaan van inloggegevens
- 7.15 Samenvatting
-
8. Git aanpassen
- 8.1 Git configuratie
- 8.2 Git attributen
- 8.3 Git Hooks
- 8.4 Een voorbeeld van Git-afgedwongen beleid
- 8.5 Samenvatting
-
9. Git en andere systemen
- 9.1 Git als een client
- 9.2 Migreren naar Git
- 9.3 Samenvatting
-
10. Git Binnenwerk
- 10.1 Binnenwerk en koetswerk (plumbing and porcelain)
- 10.2 Git objecten
- 10.3 Git Referenties
- 10.4 Packfiles
- 10.5 De Refspec
- 10.6 Uitwisseling protocollen
- 10.7 Onderhoud en gegevensherstel
- 10.8 Omgevingsvariabelen
- 10.9 Samenvatting
-
A1. Bijlage A: Git in andere omgevingen
- A1.1 Grafische interfaces
- A1.2 Git in Visual Studio
- A1.3 Git in Visual Studio Code
- A1.4 Git in Eclipse
- A1.5 Git in Sublime Text
- A1.6 Git in Bash
- A1.7 Git in Zsh
- A1.8 Git in PowerShell
- A1.9 Samenvatting
-
A2. Bijlage B: Git in je applicaties inbouwen
- A2.1 Commando-regel Git
- A2.2 Libgit2
- A2.3 JGit
- A2.4 go-git
- A2.5 Dulwich
-
A3. Bijlage C: Git Commando’s
- A3.1 Setup en configuratie
- A3.2 Projecten ophalen en maken
- A3.3 Basic Snapshotten
- A3.4 Branchen en mergen
- A3.5 Projecten delen en bijwerken
- A3.6 Inspectie en vergelijking
- A3.7 Debuggen
- A3.8 Patchen
- A3.9 Email
- A3.10 Externe systemen
- A3.11 Beheer
- A3.12 Binnenwerk commando’s (plumbing commando’s)
7.1 Git Tools - Revisie Selectie
Op dit moment heb je de meeste van de alledaagse commando’s en workflows geleerd die je nodig hebt om een Git repository te onderhouden of te beheren voor het bijhouden van je eigen bron code. Je hebt de basale taken van tracken en committen van bestanden volbracht, en je hebt de kracht van de staging area onder de knie gekregen en het lichtgewicht topic branchen en mergen.
Nu zal je een aantal erg krachtige dingen die Git kan doen onderzoeken die je niet perse elke dag zult doen maar die je op een gegeven moment wel nodig kunt hebben.
Revisie Selectie
Git laat je op verschillende manieren een specifieke commit, een groep van commits, of een reeks van commits aangeven. Ze zijn niet echt voor de hand liggend, maar zijn zeer nuttig om te kennen.
Enkele revisies
Je kunt uiteraard refereren aan een commit met de SHA-1 hash die eraan is gegeven, maar er zijn ook meer mens-vriendelijke manieren om aan commits te referen. Deze paragraaf toont de verschillende manieren waarmee je kunt refereren aan een enkele commit.
Verkorte SHA-1
Git is slim genoeg om uit te knobbelen welke commit je wilde typen als je de eerste paar karakters geeft, zolang als je verkorte SHA-1 op z’n minst 4 karakters lang is en eenduidig; dus, slechts één object in de huidige repository begint met dat deel-SHA-1.
Bijvoorbeeld, om een specifieke commit te zien, stel dat je een git log
commando gebruikt en de commit waar je een bepaalde functie hebt toegevoegd identificeert:
$ git log
commit 734713bc047d87bf7eac9674765ae793478c50d3
Author: Scott Chacon <schacon@gmail.com>
Date: Fri Jan 2 18:32:33 2009 -0800
fixed refs handling, added gc auto, updated tests
commit d921970aadf03b3cf0e71becdaab3147ba71cdef
Merge: 1c002dd... 35cfb2b...
Author: Scott Chacon <schacon@gmail.com>
Date: Thu Dec 11 15:08:43 2008 -0800
Merge commit 'phedders/rdocs'
commit 1c002dd4b536e7479fe34593e72e6c6c1819e53b
Author: Scott Chacon <schacon@gmail.com>
Date: Thu Dec 11 14:58:32 2008 -0800
added some blame and merge stuff
Stel dat we geinteresseerd zijn in de commit waarvan de hash begint met 1c002dd....
.
Je kunt deze commit bekijken met elk van de volgend variaties van het git show
commando (aangenomen dat de kortere versies uniek zijn):
$ git show 1c002dd4b536e7479fe34593e72e6c6c1819e53b
$ git show 1c002dd4b536e7479f
$ git show 1c002d
Git kan met een korte, unieke afkorting van je SHA-1 waarden overweg.
Als je --abbrev-commit
doorgeeft aan het git log
commando, zal de uitvoer de korte waarden gebruiken, maar ze uniek houden; het gebruikt standaard zeven karakters, maar zal ze langer maken als dat nodig is om de SHA-1 eenduidig te houden:
$ git log --abbrev-commit --pretty=oneline
ca82a6d changed the version number
085bb3b removed unnecessary test code
a11bef0 first commit
Over het algemeen zijn acht tot tien karakters meer dan genoeg om binnen een project uniek te zijn. Om een voorbeeld te geven: per februari 2019 bevat de Linux kernal (wat een redelijk groot project is) meer dan 875.000 commits en bijna zeven miljoen objecten in de object database, waarin geen twee objecten waavan de SHA-1s in de eerste 12 karakters gelijk zijn.
Noot
|
EEN KORTE NOOT OVER SHA-1
Veel mensen zijn bezorgd dat op een gegeven moment ze, door domme toeval, twee objecten in hun repository hebben waarvan de hash dezelfde SHA-1 waarde is. Wat dan? Als het je overkomt dat je een object commit dat naar dezelfde SHA-1 waarde hasht als een vorig ander object in je repository, zal Git het vorige object in je Git database zien, aannemen dat het al was weggeschreven en simpelweg herbruiken. Als je op dat moment dat object weer zou gaan uitchecken, zal je altijd de gegevens van het eerste object krijgen. Echter, je moet beseffen hoe belachelijk onwaarschijnlijk dit scenario is.
De SHA-1 cijferruimte is 20 bytes of 160 bits.
De hoeveelheid willekeurig gehashde objecten die nodig zijn om een 50% waarschijnlijkheid van een enkele botsing te
garanderen is ongeveer 280 (de formule om de waarschijnlijkheid van een botsing te bepalen is Hier is een voorbeeld om je een idee te geven wat er nodig is om een SHA-1 botsing te krijgen. Als alle 6,5 miljard mensen op Aarde zouden programmeren, en elke seconde zou elk van hen code opleveren ter grootte aan de gehele Linux kernel historie (6,5 miljoen Git objecten) en deze pushen naar een gigantische Git repository, zou het ongeveer 2 jaar duren voordat de repository genoeg objecten zou bevatten om een 50% waarschijnlijkheid te krijgen van een enkele SHA-1 object botsing. Er is een grotere kans dat elk lid van je programmeerteam wordt aangevallen en gedood door wolven in ongerelateerde gebeurtenissen op dezelfde avond. |
Branch referenties
Een directe manier om naar een specifieke commit te verwijzen is als het de commit is aan de punt van een branch; in dat geval kan je de branchnaam in elke Git commando gebruiken die een referentie naar een commit verwacht.
Bijvoorveeld, als je het laatste commit object op een branch wilt laten zien, zijn de volgende commando’s gelijk, aangenomen dat de topic1
-branch wijst naar ca82a6d
:
$ git show ca82a6dff817ec66f44342007202690a93763949
$ git show topic1
Als je wilt zien naar welke specifieke SHA-1 een branch wijst, of als je wilt zien waar elk van deze voorbeelden op neerkomt in termen van SHA-1s, kan je het Git binnenwerk instrument (plumbing tool) geheten rev-parse
gebruiken.
Je kunt Git Binnenwerk bekijken voor meer informatie over plumbing tools; het komt erop neer dat rev-parse
er is voor onder-water operaties en dat het niet bedoeld is voor het dagelijks gebruik.
Dit gezegd hebbende, het kan soms handig zijn als het nodig is om te zien wat er echt gebeurt.
Hier kan je rev-parse
op je branch laten lopen.
$ git rev-parse topic1
ca82a6dff817ec66f44342007202690a93763949
RefLog verkorte namen
Een van de dingen die Git op de achtergrond doet als je aan het werk bent is een “reflog” bijhouden — een logboek waarin wordt bijgehouden waar je HEAD en branch referenties in de afgelopen paar maanden zijn geweest.
Je kunt de reflog zien door git reflog
te gebruiken:
$ git reflog
734713b HEAD@{0}: commit: fixed refs handling, added gc auto, updated
d921970 HEAD@{1}: merge phedders/rdocs: Merge made by the 'recursive' strategy.
1c002dd HEAD@{2}: commit: added some blame and merge stuff
1c36188 HEAD@{3}: rebase -i (squash): updating HEAD
95df984 HEAD@{4}: commit: # This is a combination of two commits.
1c36188 HEAD@{5}: rebase -i (squash): updating HEAD
7e05da5 HEAD@{6}: rebase -i (pick): updating HEAD
Elke keer als de punt van je branch voor welke reden dan ook wordt bijgewerkt, slaat Git die informatie voor je op in deze tijdelijke historie.
En je kunt ook aan oudere commits refereren met deze gegevens.
Als je bijvoorbeeld de vijfde vorige waarde van de HEAD van je repository wilt zien, kan je de @{5}
referentie gebruiken die je in de reflog uitvoer ziet:
$ git show HEAD@{5}
Je kunt deze syntax ook gebruiken om te zien waar een branch was op een specifieke moment in het verleden.
Als je bijvoorbeeld wilt zien waar je master
-branch gister was, kan je dit typen
$ git show master@{yesterday}
Dat toont je waar de punt van de master
-branch gister was.
Deze techniek werkt alleen voor gegevens die nog steeds in je reflog staan, dus je kunt het niet gebruiken om commits op te zoeken die ouder dan een paar maanden zijn.
Om de reflog informatie geformatteerd te tonen zoals de git log
uitvoer, kan je git log -g
uitvoeren:
$ git log -g master
commit 734713bc047d87bf7eac9674765ae793478c50d3
Reflog: master@{0} (Scott Chacon <schacon@gmail.com>)
Reflog message: commit: fixed refs handling, added gc auto, updated
Author: Scott Chacon <schacon@gmail.com>
Date: Fri Jan 2 18:32:33 2009 -0800
fixed refs handling, added gc auto, updated tests
commit d921970aadf03b3cf0e71becdaab3147ba71cdef
Reflog: master@{1} (Scott Chacon <schacon@gmail.com>)
Reflog message: merge phedders/rdocs: Merge made by recursive.
Author: Scott Chacon <schacon@gmail.com>
Date: Thu Dec 11 15:08:43 2008 -0800
Merge commit 'phedders/rdocs'
Het is belangrijk op te merken dat de reflog informatie puur lokaal is — het is een log van wat jij gedaan hebt in jouw repository.
De referentie zal niet hetzelfde zijn op de kopie van een ander van de repository, en direct nadat je initieel een kloon van een repository gemaakt hebt zal je een lege reflog hebben, omdat er nog geen activiteiten hebben plaatsgevonden op jouw repository.
Het uitvoeren van git show HEAD@{2.months.ago}
zal alleen werken als je het project op z’n minst 2 maanden geleden hebt gekloond — als je het recentelijker geleden hebt gekloond zal je alleen je eerste lokale commit zien.
Tip
|
Zie de reflog als Git’s versie van shell history
Als je een UNIX of Linux achtergrond hebt, kan je de reflog zien als Git’s versie van shell history, wat benadrukt dat wat er hier te zien is duidelijk alleen relevant is voor jou en jouw “sessie” en niets te doen heeft met anderen die misschien toevallig op dezelfde machine werken. |
Voorouder referenties
De andere veelgebruikte manier om een commit te specificeren is via zijn voorouders.
Als je een ^
(caret) aan het eind van een referentie plaatst, zal Git dit interpreteren als een referentie aan de ouder van deze commit.
Stel dat je naar de historie van je project kijkt:
$ git log --pretty=format:'%h %s' --graph
* 734713b fixed refs handling, added gc auto, updated tests
* d921970 Merge commit 'phedders/rdocs'
|\
| * 35cfb2b Some rdoc changes
* | 1c002dd added some blame and merge stuff
|/
* 1c36188 ignore *.gem
* 9b29157 add open3_detach to gemspec file list
Dan kan je de vorige commit zien door HEAD^
te specificeren, wat “de ouder van HEAD” betekent:
$ git show HEAD^
commit d921970aadf03b3cf0e71becdaab3147ba71cdef
Merge: 1c002dd... 35cfb2b...
Author: Scott Chacon <schacon@gmail.com>
Date: Thu Dec 11 15:08:43 2008 -0800
Merge commit 'phedders/rdocs'
Noot
|
De caret escapen op Windows
Voor
|
Je kunt ook een getal aangeven na de ^
om aan te geven welke ouder je wilt; bijvoorbeeld: d921970^2
wat “de tweede ouder van d921970” betekent.
Deze syntax is alleen nuttig voor merge commits, waar je meer dan een ouder hebt.
De eerste ouderr van een merge commit is van de branch waar je op stond toen je mergede (meestal master
), terwijl de tweede ouder van een merge commit van de branch is die werd gemerged (zeg, topic
):
$ git show d921970^
commit 1c002dd4b536e7479fe34593e72e6c6c1819e53b
Author: Scott Chacon <schacon@gmail.com>
Date: Thu Dec 11 14:58:32 2008 -0800
added some blame and merge stuff
$ git show d921970^2
commit 35cfb2b795a55793d7cc56a6cc2060b4bb732548
Author: Paul Hedderly <paul+git@mjr.org>
Date: Wed Dec 10 22:22:03 2008 +0000
Some rdoc changes
De andere belangrijke voorouder specificatie is de ~
(tilde).
Deze refereert ook aan de eerste ouder, dus HEAD~
en HEAD^
zijn aan elkaar gelijk.
Het verschil wordt duidelijk wanneer je een getal specificeert.
HEAD~2
betekent “de eerste ouder van de eerste ouder”, of “de grootouder” — het loopt het aantal keren terug over de eerste ouders dat je specificeert.
Even weer als voorbeeld, in de historie van hiervoor, HEAD~3
zou dit opleveren:
$ git show HEAD~3
commit 1c3618887afb5fbcbea25b7c013f4e2114448b8d
Author: Tom Preston-Werner <tom@mojombo.com>
Date: Fri Nov 7 13:47:59 2008 -0500
ignore *.gem
Dit kan ook als HEAD~~~
worden geschreven, wat wederom de eerste ouder van de eerste ouder van de eerste ouder aanduidt:
$ git show HEAD~~~
commit 1c3618887afb5fbcbea25b7c013f4e2114448b8d
Author: Tom Preston-Werner <tom@mojombo.com>
Date: Fri Nov 7 13:47:59 2008 -0500
ignore *.gem
Je kunt deze syntaxen ook combineren; je kunt de tweede ouder van de vorige referentie krijgen (aangenomen dat het een merge commit was) door HEAD~3^2
te gebruiken, en zo voort.
Commit reeksen
Nu dat je individuele commits kunt aanwijzen, laten we eens kijken hoe je een reeks van commits kunt aanduiden. Dit is in het bijzonder nuttig voor het beheren van je branches — als je veel branches hebt, kan je reeks-specificaties gebruiken om vragen te beantwoorden als “Welk werk zit op deze branch die ik nog niet gemerged heb in mijn hoofdbranch?”.
Tweevoudige punt
De meest gebruikte reeks specificatie is de tweevoudige punt (double-dot) syntax. Dit vraagt Git gewoon om een reeks commits op te halen die bereikbaar zijn van de ene commit maar niet vanaf een andere. Bijvoorbeeld, stel dat je een commit historie hebt die eruit ziet als Voorbeeld historie voor reeks selectie..
Je wilt zien wat er in je experiment
-branch zit wat nog niet in je master
-branch gemerged is.
Je kunt Git vragen om een log te laten zien van alleen die commits met master..experiment
— hiermee wordt bedoeld “alle commits bereikbaar voor experiment die niet bereikbaar zijn voor master.”
Om het kort en duidelijk te houden in deze voorbeelden, gebruik ik de letters van de commit objecten uit het diagram in plaats van de eigenlijke log uitvoer in de volgorde dat ze getoond zouden zijn:
$ git log master..experiment
D
C
Als je, aan de andere kant, je het tegenovergestelde wilt zien — alle commits in master
die niet in experiment
zitten, kan je de branch namen omdraaien.
experiment..master
laat je alles in master
zien wat niet vanuit experiment
bereikbaar is:
$ git log experiment..master
F
E
Dit is nuttig als je de experiment
-branch bij wilt houden en alvast wilt zien wat je op het punt staat in te mergen.
Waar deze syntax ook vaak voor wordt gebruikt is om te zien wat je op het punt staat te pushen naar een remote:
$ git log origin/master..HEAD
Dit commando laat je alle commits in je huidige branch zien die niet in de master
-branch zitten op je origin
-remote.
Als je een git push
laat lopen en je huidige branch trackt origin/master
, zijn de commits die worden getoond door git log origin/master..HEAD
de commits die naar de server zullen worden gestuurd.
Je kunt ook een kant van deze sytax weglaten om Git te laten aannemen dat hier HEAD wordt bedoeld.
Bijvoorbeeld, kan je dezelfde resultaten bereiken als in het vorige voorbeeld door git log origin/master..
te typen — Git gebruikt HEAD als een van de twee kanten ontbreekt.
Meerdere punten
De twee-punten syntax is nuttig als een afkorting; maar misschien wil je meer dan twee branches aanwijzen om je revisie aan te geven, zoals het zien welke commits er zijn in een willekeurig aantal branches die niet in de branch zitten waar je nu op zit.
Git staat je toe dit te doen door ofwel het ^
karakter te gebruiken of --not
voor elke referentie waarvan je niet de bereikbare commits wilt zien.
Dus deze drie commando’s zijn gelijkwaardig:
$ git log refA..refB
$ git log ^refA refB
$ git log refB --not refA
Dit is nuttig omdat je met deze syntax meer dan twee referenties in je query kunt aangeven, wat je niet kunt doen met de dubbele-punt syntax.
Als je bijvoorbeeld alle commits wilt zien die bereikbaar zijn vanaf refA
of refB
maar niet van refC
, kan je een van deze intypen:
$ git log refA refB ^refC
$ git log refA refB --not refC
Dit vormt een hele krachtige revisie-uitvraag-systeem die je kan helpen om uit te vinden wat er in je branches zit.
Drievoudige punt
De laatste belangrijke reeks-selectie syntax is de drievoudige punt (triple dot) syntax, welke alle commits aanduidt
die door een van beide referenties bereikbaar is maar niet door beide.
Kijk even terug naar het voorbeeld van commit historie in Voorbeeld historie voor reeks selectie..
Als je wilt zien wat in master
of experiment
zit maar geen gedeelde referenties kan je dit laten lopen
$ git log master...experiment
F
E
D
C
Wederom, dit geeft je een normale log
uitvoer, maar laat je alleen de commit informatie zien voor deze vier commits, getoond op de reguliere commit datum-volgorde.
Een gebruikelijke optie om te gebruiken bij het log
commando in dit geval is --left-right
, welke je laat zien welke zijde van de reeks elke commit in zit.
Dit helpt om de gegevens meer bruikbaar te maken:
$ git log --left-right master...experiment
< F
< E
> D
> C
Met deze instrumenten kan je eenvoudiger Git laten weten welke commit of commits je wilt onderzoeken.