This is an in-progress translation.
To help translate the book, please fork the book at GitHub and push your contributions.

Git configuratie

Zoals je kort in Hoofdstuk 1 gezien hebt, kun je Git configuratie instellingen specificeren met het git config commando. Een van de eerste dingen die je deed wat je naam en e-mail adres instellen:

$ git config --global user.name "John Doe"
$ git config --global user.email johndoe@example.com

Nu zul je een paar van de meer interessante opties leren, die je op deze manier kunt instellen om je Git op maat te maken.

Je zag wat eenvoudige Git configuratie details in het eerste hoofdstuk, maar ik zal ze hier nog eens snel laten zien. Git gebruikt een aantal configuratie bestanden om het niet-standaard gedrag dat je wil te bepalen. De eerste plaats waar Git kijkt voor deze waarden is in een /etc/gitconfig bestand, wat de waarden bevat voor alle gebruikers op het systeem en al hun repositories. Als je de optie --systeem aan git config meegeeft, leest en schrijft het specifiek naar dit bestand.

De volgende plaats waar Git kijkt is het ~/.gitconfig bestand, wat specifiek is voor iedere gebruiker. Je kunt er voor zorgen dat Git naar dit bestand leest en schrijft door de --global optie mee te geven.

Als laatste kijkt Git naar configuratie waarden in het config bestand in de Git map (.git/config) of welk repository dat je op dat moment gebruikt. Deze waarden zijn specifiek voor dat ene repository. Ieder niveau overschrijft de waarden in het vorige niveau, dus waarden in .git/config gaan boven die in /etc/gitconfig, bijvoorbeeld. Je kunt die waarden ook instellen door het bestand handmatig aan te passen en de correcte syntax in te voegen, maar het is over het algemeen makkelijk m het git config commando uit te voeren.

Basis client configuratie

De configuratie opties die herkent worden door Git vallen binnen twee categorieën: de client kant en de server kant. De meerderheid van de opties zijn voor de client kant – de configuratie van je persoonlijke voorkeuren. Alhoewel er massa’s opties beschikbaar zijn, zal ik alleen een paar behandelen die ofwel veelgebruikt zijn of je werkwijze significant kunnen beïnvloeden. Veel opties zijn alleen bruikbaar in randgevallen waar ik hier niet naar kijk. Als je een lijst van alle opties wil zien, die jou versie van Git herkent kun je dit uitvoeren

$ git config --help

De gebruikershandleiding voor git config toont alle beschikbare opties in groot detail.

core.editor

Standaard zal Git de standaard tekst editor gebruiken, die je hebt ingesteld of anders terugvallen op de Vi editor om je commit en tag boodschappen te maken of te wijzigen. Om die instelling naar iets anders om te zetten, kun je de core.editor instelling gebruiken:

$ git config --global core.editor emacs

Zonder dat het uitmaakt wat je als je standaard shell editor waarde ingesteld hebt, zal Git Emacs starten om boodschappen aan te passen.

commit.template

Als je dit als een pad instelt dat naar een bestand op je systeem wijst, zal Git dat bestand als de standaard boodschap gebruiken als je commit. Bijvoorbeeld, stel dat je een sjabloon bestand aanmaakt als $HOME/.gitmessage.txt die er zo uitziet:

onderwerp regel

wat er gebeurd is

[ticket: X]

Om Git te vertellen dat het dit moet gebruiken als standaard boodschap dat in je editor moet verschijnen als je git commit uitvoert, stel je de commit.template configuratie waarde in:

$ git config --global commit.template $HOME/.gitmessage.txt
$ git commit

Daarna zal je editor zoiets als dit openen als je standaard commit boodschap als je commit:

onderwerp regel

wat er gebeurd is

[ticket: X]
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
# modified:   lib/test.rb
#
~
~
".git/COMMIT_EDITMSG" 14L, 297C

Als je een beleid hebt voor commit boodschappen, dan vergroot het plaatsen van een sjabloon voor dat beleid op je systeem en het configureren ervan voor Git om het als standaard te gebruiken de kans dat dat beleid met regelmaat gevolgd wordt.

core.pager

De instelling voor ‘core.pager’ bepaald welke pagineer applicatie gebruikt wordt door Git om de uitvoer van log en diff weer te geven. Je kunt het instellen als more of als je favoriete pagineerder (standaard is het less), of je kunt het uit zetten door het als een lege tekst in te stellen:

$ git config --global core.pager ''

Als je dat uitvoert, zal Git de gehele uitvoer van alle commando’s pagineren, hoe lang het ook is.

user.signingkey

Als je gebruik maakt van ondertekende tags (zoals besproken in Hoofdstuk 2), dan maakt het instellen van je GPG signeer sleutel als configuratie instelling het leven eenvoudiger. Stel je sleutel ID zo in:

$ git config --global user.signingkey <gpg-key-id>

Nu kun je je tags signeren zonder steeds je sleutel op te hoeven geven bij het git tag commando:

$ git tag -s <tag-name>

core.excludesfile

Je kunt patronen in het .gitignore bestand van je project zetten zodat Git ze niet ziet als ongevolgde bestanden of ze niet zal proberen te stagen als je git add op ze uitvoert, zoals besproken in Hoofdstuk 2. Maar als je wilt dat een ander bestand buiten je project die waarden of extra waarden bevat, kun je Git vertellen met de core.excludesfile vertellen waar dat bestand is. Stel het eenvoudigweg in als een pad naar een bestand dat een inhoud heeft dat vergelijkbaar is met wat een .gitignore bestand zou hebben.

help.autocorrect

Deze optie is alleen beschikbaar in Git 1.6.1. en later. Als je een commando in Git 1.6 verkeerd typt, toont het je zoiets als dit:

$ git com
git: 'com' is not a git-command. See 'git --help'.

Did you mean this?
     commit

Als je het.autocorrect op 1 instelt, zal Git automatisch het commando uitvoeren als het slechts één passend commando heeft in dit scenario.

Kleuren in Git

Git kan zijn uitvoer in je terminal kleuren, wat je kan helpen om de uitvoer snel en eenvoudig visueel te begrijpen. Een aantal opties kan je helpen om de kleuren naar je voorkeur in te stellen.

color.ui

Git zal automatisch het meeste van zijn uitvoer kleuren als je het vraagt. Je kunt erg specifiek zijn in wat je gekleurd wil en hoe; maar om alle standaard kleuren in de terminal aan te zetten, stel dan color.ui in op true:

$ git config --global color.ui true

Als deze waarde ingesteld is, zal Git zijn uitvoer kleuren zodra deze naar een terminal gaat. Andere mogelijke opties zijn false, wat de uitvoer nooit kleurt, en always, wat de kleuren altijd weergeeft, zelfs als je Git commando’s omleidt naar een bestand of naar een ander commando doorsluist. Deze instelling is toegevoegd in Git 1.5; als je een oudere versie hebt, zul je alle kleuren instellingen individueel in moeten stellen.

Je zult zelden color.ui = always willen. In de meeste scenario’s, als je kleuren in je omgeleide uitvoer wil, kun je een --color vlag aan het Git commando meegeven om het te forceren kleuren te gebruiken. De color.ui = true instelling is vrijwel altijd hetgene je wil gebruiken.

color.*

Als je meer specifiek wil zijn welke commando’s gekleurd moeten zijn en hoe, of je hebt een oudere versie, dan voorziet Git in woord specifieke kleuren instellingen. Ieder van deze kan worden ingesteld op true, false of always:

color.branch
color.diff
color.interactive
color.status

Daarnaast heeft ieder van deze ook sub-instellingen die je kunt gebruiken om specifieke kleuren in te stellen voor delen van de uitvoer, als je iedere kleur wilt overschrijven. Bijvoorbeeld, om de meta informatie in je diff uitvoer in blauwe voorgrond, zwarte achtergrond en vetgedrukt in te stellen, kun je dit uitvoeren

$ git config --global color.diff.meta “blue black bold”

Je kunt de kleur instellen op ieder van de volgende waarden: normal, black, red, green, yellow, blue, magenta, cyan, of white. Als je een attribuut wil hebben, zoals vetgedrukt in het vorige voorbeeld, kun je kiezen uit bold, dim, ul, blink en reverse.

Zie de manpage van git config voor alle sub-instellingen die je kunt instellen, als je dat wil.

Externe merge en diff tools

Alhoewel Git een interne implementatie van diff heeft, die je tot nog toe gebruikte, kun je in plaats daarvan een extern tool instellen. Je kunt ook een grafisch samenvoeg conflict-oplossings tool instellen, in plaats van handmatig de conflicten op te moeten lossen. Ik zal nu demonstreren hoe je het Perforce Visuele Samenvoeg Tool (P4Merge) in moet stellen, om je diff en samenvoeg oplossingen te doen, omdat het een fijn grafisch tool is en omdat het gratis is.

P4Merge werkt op alle grote platformen als je dit wil proberen, dus je zou het moeten kunnen doen. Ik zal in de voorbeelden paden gebruiken die op Mac en Linux systemen werken; voor Windows moet je /usr/local/bin veranderen in een pad naar een uitvoerbaar bestand in je omgeving.

Je kunt P4Merge hier downloaden:

http://www.perforce.com/perforce/downloads/component.html

Om te beginnen zul je externe wrapper scripts instellen om je commando’s uit te voeren. Ik zal het Mac pad gebruiken voor de applicatie; in andere systemen zal het moeten wijzen naar waar de p4merge binary geïnstalleerd is. Stel een samenvoeg wrapper script in, genaamd extMerge, die je applicatie met alle meegegeven argumenten aanroept:

$ cat /usr/local/bin/extMerge
#!/bin/sh
/Applications/p4merge.app/Contents/MacOS/p4merge $*

De diff wrapper controleert dat er zeker zeven argumenten meegegeven zijn, en geeft twee ervan aan je samenvoeg script. Standaard geeft Git de volgende argumenten aan het diff programma mee:

path old-file old-hex old-mode new-file new-hex new-mode

Omdat je alleen de oude-bestand en nieuwe-bestand argumenten wil, zul je het wrapper script gebruiken om degenen door te geven die je wil.

$ cat /usr/local/bin/extDiff
#!/bin/sh
[ $# -eq 7 ] && /usr/local/bin/extMerge "$2" "$5"

Je moet er ook zeker van zijn dat deze tools uitvoerbaar zijn:

$ sudo chmod +x /usr/local/bin/extMerge
$ sudo chmod +x /usr/local/bin/extDiff

Nu kun je je config bestand instellen dat het je eigengemaakte samenvoeg en diff tools gebruikt. Dit wordt gedaan met een aantal eigen instellingen: merge.tool om Git te vertellen welke strategie hij moet gebruiken, mergetool.*.cmd om te specificeren hoe het het commando moet uitvoeren, mergetool.trustExitCode om Git te vertellen of de exit code van dat programma een succesvolle samenvoeging betekent of niet, en diff.external om Git te vertellen welk commando het moet uitvoeren voor diffs. Dus, je kunt of vier configuratie commando’s uitvoeren

$ git config --global merge.tool extMerge
$ git config --global mergetool.extMerge.cmd \
    'extMerge "$BASE" "$LOCAL" "$REMOTE" "$MERGED"'
$ git config --global mergetool.trustExitCode false
$ git config --global diff.external extDiff

of je kunt je ~/.gitconfig bestand aanpassen en deze regels toevoegen:

[merge]
  tool = extMerge
[mergetool "extMerge"]
  cmd = extMerge "$BASE" "$LOCAL" "$REMOTE" "$MERGED"
  trustExitCode = false
[diff]
  external = extDiff

Nadat dit alles ingesteld is, zul je als je diff commando’s zoals deze uitvoert:

$ git diff 32d1776b1^ 32d1776b1

in plaat van de uitvoer van diff op de commando regel, een instantie van P4Merge gestart door Git krijgen, wat er uitziet zoals in Figuur 7-1.


Figuur 7-1. P4Merge.

Als je twee branches probeert samen te voegen en je krijgt conflicten, dan kun je het git mergetool commando uitvoeren; het start P4Merge op om je het conflict op te laten lossen met behulp van dat GUI tool.

Het aardige van deze wrapper opstelling is dat je je diff en merge tools eenvoudig aan kunt passen. Bijvoorbeeld, om je extDiff en extMerge tools in te stellen dat ze in plaats daarvan het KDiff3 tool uitvoeren, is het enige dat je moet doen je extMerge bestand aanpassen:

$ cat /usr/local/bin/extMerge
#!/bin/sh
/Applications/kdiff3.app/Contents/MacOS/kdiff3 $*

Nu zal Git het KDiff3 tool gebruiken voor het tonen van diff en het oplossen van samenvoeg conflicten.

Git is al ingesteld om een aantal andere conflict-oplossings tools te gebruiken zonder dat je de cmd configuratie in hoeft te stellen. Je kunt je merge tool op kdiff3 instellen, of opendiff, tkdiff, meld, xxdiff, emerge, vimdiff of gvimdiff. Als je niet geïnteresseerd bent in het gebruik van KDiff3 als diff, maar het liever alleen wilt gebruiken voor conflict oplossing, en het kdiff3 commando zit in je pad, dan kun je dit uitvoeren

$ git config --global merge.tool kdiff3

Als je dit uitvoert in plaats van de extMerge en extDiff bestanden in te stellen, zal Git KDiff3 gebruiken voor conflict oplossing en het normale Git diff tool voor diffs.

Opmaak en witruimten

Problemen met opmaak en witruimten zijn één van de veelvoorkomende frustrerende en subtiele problemen die veel ontwikkelaars tegenkomen bij het samenwerken, in het bijzonder over verschillende platformen. Het is heel eenvoudig voor patches en ander werk om subtiele witruimte veranderingen te introduceren, omdat editors ze stil introduceren of omdat Windows programmeurs harde returns aan het eind van de regels toevoegen die ze aanraken in gekruiste platformprojecten. Git heeft een aantal configuratie opties om met deze problemen te helpen.

core.autocrlf

Als je op Windows programmeert, of een ander systeem gebruikt maar samenwerkt met mensen die op Windows werken, zul je vroeg of laat waarschijnlijk tegen regeleinde problemen aanlopen. Dat komt omdat Windows zowel een harde return als ook een linefeed karakter gebruikt voor regeleindes in zijn bestanden, waar Mac en Linux systemen alleen het linefeed karakter gebruiken. Dit is een subtiel maar verschrikkelijk irritant feit van het werken met gekruiste platformen.

Git kan hiermee omgaan door CRLF regeleinden automatisch om te zetten naar LF zodra je commit, en vice versa op het moment dat je code uitchecked op je systeem. Je kunt deze functionaliteit aanzetten met de core.autocrlf instelling. Als je op een Windows machine zit, stel het dan in op true – dit veranderd LF regeleinden in CRLF zodra je code uitchecked:

$ git config --global core.autocrlf true

Als je op een Linux of Mac systeem zit dat LF regeleinden gebruikt, dan wil je niet dat Git ze automatisch veranderd op het moment dat Git bestanden uitchecked; maar als een bestand met CRLF regeleinden onverhoopt toch geïntroduceerd wordt, dan wil je misschien dat Git dit repareert. Je kunt Git vertellen dat je wilt dat hij CRLF in LF veranderd tijdens het committen, maar niet de andere kant op door het instellen van core.autocrlf op input:

$ git config --global core.autocrlf input

Deze instelling zal CRLF regeleinden in Windows checkouts gebruiken, en LF einden in Mac en Linux systemen en in het repository moeten laten.

Als je een Windows programmeur bent, die een alleen-Windows project doet, dan kun je deze functionaliteit uitzetten, waarmee de harde returns in het repository opgeslagen worden door de configuratie waarde op false te zetten:

$ git config --global core.autocrlf false

core.whitespace

Git is vooraf ingesteld om een aantal witruimte problemen te detecteren en te repareren. Het kan op vier veelvoorkomende witruimte problemen letten – twee staan er standaard aan en kunnen uitgezet worden, en twee staan er standaard niet aan, maar kunnen aangezet worden.

De twee die standaard aan staan zijn trailing-space, wat kijkt of er spaties aan het eind van een regel staan, en space-before-tab, wat kijkt of er spaties voor tabs staan aan het begin van een regel.

De twee die standaard uit staan, maar aangezet kunnen worden, zijn indent-with-non-tab, wat kijkt naar regels die met acht of meer spaties beginnen in plaats van tabs, en cr-at-eol, wat Git verteld dat harde returns aan het eind van een regel OK zijn.

Je kunt Git vertellen welke van deze je aan wil zetten door core.whitespace naar de waardes in te stellen die je aan of uit wil, gescheiden door komma’s. Je kunt waarden uitzetten door ze weg te laten uit de instelling tekst of door een - vooraf te laten gaan aan de waarde. Bijvoorbeeld, als je alles aan wil behalve cr-ar-eol, dan kun je dit doen:

$ git config --global core.whitespace \
    trailing-space,space-before-tab,indent-with-non-tab

Git zal deze problemen detecteren zodra je een git diff commando uitvoert en ze proberen te kleuren zodat je ze kunt repareren alvorens te committen. Het zal deze waarden ook gebruiken om je te helpen met patches toe te passen met git apply. Als je patches gaat toepassen, kun je Git vragen om je te waarschuwen als hij patches toepast waarin deze specifieke witruimte problemen zitten:

$ git apply --whitespace=warn <patch>

Of je kunt Git vragen om automatisch deze problemen te repareren alvorens de patch toe te passen:

$ git apply --whitespace=fix <patch>

Deze opties zijn ook op de git rebase optie van toepassing. Als je witruimte problemen gecommit hebt maar ze nog niet stroomopwaarts gepushed hebt, kun je een rebase uitvoeren met de --whitespace=fix optie uitvoeren om Git automatisch witruimte problemen te laten repareren zodra het de patches herschrijft.

Server configuratie

Er zijn lang niet zoveel configuratie opties beschikbaar voor de server kant van Git, maar er zijn er een paar interessante bij waar je misschien notie van wil hebben.

receive.fsckObjects

Standaard zal Git niet alle objecten die hij ontvangt gedurende een push op consistentie controleren. Alhoewel Git kan controleren of ieder object nog steeds bij zijn SHA-1 checksum past en naar geldige objecten wijst, doet hij dat niet standaard bij iedere push. Dit is een relatief dure operatie en kan veel tijd kosten voor iedere push, afhankelijk van de grootte van het repository of de push. Als je wil dat Git ieder object op consistentie controleert bij iedere push, dan kun je hem dwingen door receive.fsckObjects op true te zetten:

$ git config --system receive.fsckObjects true

Nu zal Git de integriteit van je repository controleren voor iedere push geaccepteerd wordt, om er zeker van te zijn dat kapotte clients geen corrupte gegevens introduceren.

receive.denyNonFastForwards

Als je commits rebased die je al gepushed hebt en dan nog eens pushed, of op een andere manier een commit probeert te pushen naar een remote branch die niet de commit bevat waarnaar de remote branch op het moment wijst, dan wordt dat afgewezen. Dit is over het algemeen een goed beleid; maar in het geval van de rebase, kun je besluiten dat je weet waar je mee bezig bent en kun je de remote branch geforceerd vernieuwen door een -f vlag met je push commando mee te geven.

Om de mogelijkheid van het geforceerd vernieuwen van remote branches naar niet fast-forward referenties uit te schakelen, stel je receive.denyNonFastForwards in:

$ git config --system receive.denyNonFastForwards true

Een andere manier waarop je dit kunt doen is het instellen van ontvangst haken op de server, wat we zo meteen gaan behandelen. Die aanpak staat je toe meer complexe dingen te doen, zoals het weigeren van niet fast-forwards aan een bepaalde set gebruikers.

receive.denyDeletes

Een van de wegen om een denyNonFastForwards beleid heen is dat de gebruiker de branch verwijderd en het dan opnieuw terug pushed met de nieuwe referentie. In nieuwere versies van Git (beginnend bij versie 1.6.1), kun je receive.denyDeletes op true zetten:

$ git config --system receive.denyDeletes true

Dit weigert branch en tag verwijdering door middel van een push over de hele breedte – geen enkele gebruiker mag het meer. Om remote branches te verwijderen, moet je de ref bestanden handmatig verwijderen van de server. Er zijn ook interessantere manieren om dit te doen op een per gebruiker basis door middel van ACL’s, zoals je zult leren aan het eind van dit hoofdstuk.