Finalist

Finalist Developers Blog

Git – Fast Version Control System

12 January 2009 17:43 · Stefan Borsje · Algemeen

Het bestaan van Git zal met name Linux ontwikkelaars en Ruby on Rails ontwikkelaars niet ontgaan zijn. Maar ook Perl, X.Org, Qt en Googles mobiele platform Android gebruiken Git als versiebeheersysteem. Maar hoe werkt Git precies? En wat zijn de voordelen van Git ten opzichte van bijvoorbeeld CVS of Subversion?

Historie

De ontwikkeling van Git is in 2005 door de hoofdontwikkelaar van de Linuxkernel (Linus Torvalds) gestart. Het kernelteam werkte op dat moment met BitMover’s BitKeeper. In 2005 besloot BitMover echter een punt te zetten achter de opensource variant, omdat BitMover van mening was dat enkele developers de licentie hadden geschonden door BitKeeper protocollen te reverse engineeren.
Omdat Torvalds er niet in kon slagen een waardig alternatief te vinden voor BitKeeper, besloot hij zelf door middel van een aantal C-programma’s en scripts een alternatief te ontwikkelen genaamd Git.

Een aantal belangrijke features van Git zijn:

  • Distributed versioning, er is dus geen centrale server zoals bij CVS of Subversion. Hierdoor kan Git dus zowel online als offline gebruikt worden, aangezien iedere ‘checkout’ de volledige repository (inclusief alle historie) bevat.
  • Support voor non-linaire ontwikkeling. Branchen en mergen in Git is zeer eenvoudig en wordt dan ook sterk aangemoedigd.
  • Support voor publicatie via HTTP, FTP, rsync of ssh. Hierdoor kunnen repositories gemakkelijk gesynchroniseerd worden.
  • De naam van objecten in Git bestaat uit de SHA1 hash van de content. Dit levert een aantal belangrijke voordelen op:
    • Duplicaten kunnen snel gedetecteerd worden, een vergelijking van de hash is voldoende.
    • Objecten worden (onafhankelijk van de repository) altijd onder dezelfde naam opgeslagen.
    • De mogelijkheid om te detecteren of de content niet corrupt geraakt is door te controleren of de SHA1 hash van de content nog steeds dezelfde is als de objectnaam.
  • Geen clutter zoals bij Subversion waarbij in iedere directory een .svn-directory wordt geplaatst, maar alleen een enkele .git-directory in de root. Dit levert erg veel praktische voordelen op bij het verplaatsen of verwijderen van files en subdirectories.

Installatie

Git is voornamelijk ontwikkeld op Linux, maar kan op de meeste andere Unix-achtige besturingssystemen gebruikt worden.

Om Git op een Linux systeem te installeren, is het mogelijk om op de volgende manier te compilen:

$ wget http://kernel.org/pub/software/scm/git/git-1.6.1.tar.bz2
$ tar jxpvf git-1.6.1.tar.bz2
$ cd git-1.6.1
$ make prefix=/usr all doc info
$ sudo make prefix=/usr install install-doc install-info

Voor de meeste distributies zijn er ook packages aanwezig in de packagemanager, welke bijvoorbeeld geinstalleerd kunnen worden doormiddel van:

$ sudo apt-get install git-core
$ sudo yum install git-core

Voor Mac OS X kan gebruik gemaakt worden van de git-osx-installer. Ook is het mogelijk om bijvoorbeeld via MacPorts een recente versie van Git te compileren:

$ sudo port install git-core

Voor Microsoft Window zijn er twee opties, MSysGit of door gebruik te maken van POSIX emulatie zoals bijvoorbeeld via Cygwin.

Configuratie

Om er voor te zorgen dat bij Git commits de juiste naam en het juiste e-mail adres vermeld staan, is het noodzakelijk om een .gitconfig bestand in de home-directory van de gebruiker aan te maken. Dit hoeft niet handmatig, maar kan via het git config commando:

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

Ook is het mogelijk om aliases aan te maken voor veelgebruikte commando’s, zoals bijvoorbeeld:

$ git config --global alias.co checkout

Dit zorgt ervoor dat git co een alias is voor git checkout.

Om de huidige configuratie te bekijken:

$ git config --list

Aan de slag!

Het aanmaken van een git repository is vrij eenvoudig. Voer in de te beheren directory het volgende commando uit:

$ git init

Dit commando zorgt ervoor dat een .git-directory aangemaakt wordt in de huidige directory. Deze directory bevat alle informatie met betrekking tot de repository.

Om de huidige status van de git repository te bekijken:

$ git status

Dit commando toont een overzicht van de huidige status van de repository. Omdat er nog geen files toegevoegd zijn aan de repository zullen deze nu allemaal onder ‘Untracked files’ verschijnen. Bestanden welke door Git beheerd moeten worden kunnen toegevoegd worden door middel van:

$ git add README.txt

Om bestanden te negeren is het mogelijk om een .gitignore bestand aan te maken, met daar in alle relatieve paden naar te negeren bestanden. Let hierbij wel op dat paden zonder directory toegepast worden op iedere subdirectory. Het .gitignore-bestand mag ook in subdirectory’s geplaatst worden. De .gitignore-bestanden worden samen met alle andere bestanden meegecommit, zodat de paden die hierin staan gelden voor iedereen die gebruik maakt van de repository.

Om snel alle inhoud van de huidige directory toe te voegen aan de repository:

$ git add -A

Om de bestanden vervolgens daadwerkelijk te committen:

$ git commit -m "Eerste commit"

In tegenstelling tot CVS en Subversion werkt Git niet met bestanden, maar met inhoud van een bestand. Als de inhoud van een bestand gewijzigd is moet deze dus opnieuw toegevoegd worden aan de commit. Dit wordt zichtbaar zodra we de inhoud van het eerder toegevoegde README.txt bestand wijzigen en de status van de repository opvragen. Het status rapport geeft aan dat het bestand gewijzigd is, maar nog niet toegevoegd is aan de commit. Zodra doormiddel van git add het bestand toegevoegd wordt aan de commit, wordt er een snapshot van het bestand gemaakt en wordt deze toegevoegd aan de tree voor de eerstvolgende commit. Indien het bestand na deze snapshot nogmaals gewijzigd wordt, dienen ook deze wijzigingen weer toegevoegd te worden aan de eerstvolgende commit.

Om een overzicht weer te geven van alle vorige commits:

$ git log

Ook is het mogelijk om wat gedetailleerdere informatie op te vragen over vorige commits, door middel van:

$ git log --stat

Om precies te bekijken wat er gewijzigd is bij een commit:

$ git log -p

Branching en merging

Het branching model van Git zorgt ervoor dat het heel gemakkelijk wordt om branches te maken, te updaten en weer terug te mergen. Branches zijn in Git volledig onafhankelijk van elkaar, en nemen weinig ruimte in aangezien niet de gehele repository gekopiëerd hoeft te worden, maar er in plaats daarvan alleen maar nieuwe referenties naar de dataobjecten gemaakt hoeven te worden. Dit zorgt er bijvoorbeeld voor dat het mogelijk is om voor een nieuwe feature een aparte branch te maken, dit te committen, en later te besluiten of je de branch wilt mergen met de hoofdlijn (de master branch).

De huidige branches kun je bekijken met:

$ git branch

Om een nieuwe branch genaamd ‘new_feature’ aan te maken:

$ git branch new_feature

Om te switchen naar de branch new_feature:

$ git checkout new_feature

Vervolgens worden alle wijzigingen die je toevoegt aan de commit, toegevoegd aan de nieuwe branch.
Mochten er tussendoor nog wijzigingen plaatsvinden in de master branch (bijv. het met spoed fixen van een bug), is het mogelijk om de wijzigen van de master branch weer terug te mergen in de branch voor de nieuwe feature:

$ git rebase master

Ook is het mogelijk om de huidige verschillen met de master branch te bekijken:

$ git diff master new_feature

Terug switchen naar de master branch kan vervolgens weer met:

$ git checkout master

Om de wijzigingen uit de new_feature branch te mergen met de master branch:

$ git merge new_feature

Het verwijderen van een branch kan met:

$ git branch -d new_feature

Dit geeft echter wel een foutmelding zodra deze branch nog niet gemerged is. Om de branch toch te verwijderen:

$ git branch -D new_feature

Stashing

Het aanmaken van een branch kan een vervelende bijwerking hebben. Alle nog niet gecomitte wijzigingen worden namelijk ook in de branch meegenomen als niet gewijzigd. Om dit te voorkomen is het mogelijk om alle huidige wijzigingen even tijdelijk weg te zetten in een stash. Deze stash kan vervolgens bijvoorbeeld na de merge weer opgehaald worden.

Om een stash met de naam new_stash aan te maken:

$ git stash new_stash

Met git status is nu te zien dat alle wijzigingen teruggedraaid zijn. Om de huidige stashes te bekijken:

$ git stash list

Vervolgens is het nu dus mogelijk om van branch te switchen of een nieuwe branch aan te maken, zonder dat alle gestashte wijzigingen hierin zichtbaar zijn.
Om de stash weer op te halen:

$ git stash apply

Stashes kunnen opgeschoond worden met:

$ git stash clear

Remote repositories

In een team van ontwikkelaars is het handig om één repository als centrale repository te gebruiken, zodat iedereen over updates kan beschikken, zonder de noodzaak met alle individuele repositories te moeten synchroniseren. Dit kan gerealiseerd worden door bijvoorbeeld een server in te richten met een repository, maar het is ook mogelijk om gebruik te maken van diensten als GitHub of Gitorious.

Om een centrale server in te richten als centrale repository, is het voldoende om de git repository te clonen.

$ scp -r appname git@example.com:/var/git/appname

Vervolgens kan er van de repository een clone gemaakt worden, zodat de centrale server automatisch als remote repository dient:

$ git clone git@example.com:/var/git/appname

In het .git/config-bestand is alle informatie te vinden over remote repositories en branches. In dit geval is ‘example.com’ de origin repository geworden.
Om nu na een lokale commit de wijzigingen naar de centrale repository te versturen:

$ git push

Om nieuwe commits van de centrale repository te halen:

$ git pull

Om meer informatie over de centrale repository te bekijken:

$ git remote show origin

Conclusie

Het mag duidelijk zijn dat Git een aantal zeer interessante eigenschappen en functies heeft, die niet terug te vinden zijn in de wat traditionelere versiebeheersystemen zoals CVS en Subversion. Vooral de ondersteuning voor meerdere (distributed) repositories en de eenvoud van branching/merging zijn een groot pluspunt!

8 reacties »

  1. Goed stuk en altijd handig om zo’n reference te hebben!
    Weet je toevallig ook wat de voor/nadelen zijn van git tegenover andere systemen zoals Bazaar en Mercurial?

    Pascal de Vink - January 12, 2009 18:33

  2. Jazeker! Daarvoor kan ik je verwijzen naar http://nl.whygitisbetterthanx.com waar een prachtig overzicht te vinden is.

    Stefan Borsje - January 12, 2009 19:37

  3. Mooie write-up! Misschien ook leuk om te vermelden dat Git zich uitstekend leent voor Open Source development (het is dan ook bedacht door meneer Torvalds) en off-line werken. (Je hebt altijd je eigen kopie van de repository).

    Github speelt hier handig op in door code ‘sociaal’ te maken. Dus die app is wel het noemen waard.

    Ariejan de Vroom - January 12, 2009 20:04

  4. Mooie post, voor privé projecten gebruik ik Git de laatste tijd en met enorm veel plezier.

    Het gebruik van meerdere externe repositories per git-repository is erg fijn, en kijk ook eens naar braid, de oplossing voor svn-externals, zonder de ellende van uitvallende repositories.

    Iain - January 12, 2009 20:32

  5. Geh dat is nou eens vet! Begrijp ik dus goed dat ik alleen SSH server nodig heb en geen GIT server of iets dergelijks? (wat wel bij SVN het geval is/was)

    Hm… ik denk dat ik de overstap ga maken van SVN naar GIT… briljant!

    Diederick - January 15, 2009 18:12

  6. An Illustrated Guide to Git on Windows:

    http://nathanj.github.com/gitguide/

    Iain Hecker - January 20, 2009 9:31

  7. Zeg… dat ‘Fast’ in de titel…

    ik heb zelf alleen ervaring met GitHub, en moet zeggen dat het helemaal niet ‘Fast’ is… hoe is de performance als je alleen met eigen repositories werkt?

    Peter Maas - February 3, 2009 21:18

  8. “Geh dat is nou eens vet! Begrijp ik dus goed dat ik alleen SSH server nodig heb en geen GIT server of iets dergelijks? (wat wel bij SVN het geval is/was)”

    svn werkt net zo goed over ssh, zonder aparte server: svn co svn+ssh://je-ssh-server.com/home/svn/repos/project zal een project uitchecken van de server je-ssh-server.com, de directory /home/svn/repos/project. Je moet dan dus wel een shell account op die server hebben en access tot de repository.

    Tim - April 6, 2009 15:08

Reageer

RSS feed for comments on this post · TrackBack URI