Version Control

Wat is Version Control

Version Control zorgt ervoor dat alle verschillende versies van de software bijgehouden worden in een centrale database of repository. Deze repository is de “golden source” van het software product. Het bevat de code die de developers schrijven en alle aanpassingen die gemaakt werden.

Waarom is Version Control belangrijk?

Een goed version control systeem zorgt ervoor dat developers samen kunnen werken in teamverband aan een softwareproduct. Zij kunnen een kopie van de code op hun systeem bewaren en deze periodiek synchroniseren met een centrale repository server. Het kan voorvallen dat developers tegelijk aan dezelfde code aan het werken zijn en dat conflicten opduiken wanneer beiden developers hun code naar de centrale repository sturen. Deze conflicten kunnen zeer tijdrovend zijn en de keuze van een goed versiecontrole systeem helpt om de productiviteit van de developers hoog te houden.

git

Git is de gouden standaard van versiecontrolesystemen. In het verleden werd er vaak gebruik gemaakt van CVS of SVN (Subversion), maar deze systemen zijn verouderd en zeker niet zo flexibel zoals git. Wat git zo degelijk maakt, is dat git een gedistribueerd versiecontrolesysteem is. Elke developer werkt met een volledige kopie van alle versies op hun systeem, maakt veranderingen en commit (bewaart) deze veranderingen lokaal. Daarna kunnen deze commits gepusht (verzonden) worden naar de centrale repository.

Conflicten kunnen nog steeds opduiken, maar met een goede git workflow implementatie, kunnen deze tot het minimum herleid worden. Hierna bespreken we git flow, een defacto-standaard git workflow dat door developers gebruikt wordt.

git flow

Eenmaal git in gebruik is, dient het hele team een goede workflow te volgen. Zonder een goede workflow te volgen gaat development te vaak gepaard met het oplossen van conflicten en is de kans groter dat ongeteste code in een release terecht komt.

Git flow is een workflow dat er voor zorgt dat elke developer in zijn eigen versie kan programmeren, en deze eigen versie continu integreert met het werk dat andere developers op de gezamenlijke branch committen. Deze eigen versie noemt een branch in git.

_images/git-flow-1.png

git flow terminologie

Branch Doel
master Branch voor code dat uitgebracht is (release)
develop Branch dat developers gebruiken voor te committen / branchen
feature/* Branch waar de individuele developer kan committen
hotfix/* Branch dat kan gebruikt worden voor hotfixes te onwtikkelen
release/* Branch dat gebruikt wordt om een release voor te bereiden

git flow workflow

Git flow heeft altijd een master branch waar de code in zit die uitgebracht is in releases. Deze releases worden voorzien van een tag, bijvoorbeeld “1.0”. Vanaf deze master branch wordt dan een nieuwe branch gemaakt met de naam “develop”. Dit is de branch waar developers hun eigen feature/* branch vanaf kunnen starten. Wanneer de developer een nieuwe feature wenst uit te brengen start deze een nieuwe branch met als basis de develop branch. De developer ontwikkelt de nieuwe code en commit deze op zijn eigen feature branch. In geen geval gaat hij code rechtstreeks committen naar de develop of naar de master branch. Terwijl de developer code ontwikkelt, kan nieuwe (afgewerkte) code op de develop branch gezet worden. Dit betekent dat de developer nu in een feature branch zit te werken die niet up-to-date meer is. De developer zal daarom een “rebase” moeten uitvoeren op zijn feature branch om deze terug up to date te brengen. Op dat moment zal de developer mogelijke conflicten moeten oplossen, want zijn collega-developer heeft misschien aan dezelfde regels code gewerkt. De bedoeling is om continu, bijvoorbeeld elke dag (of vaker) een rebase uit te voeren, zodat de developer weet dat zijn feature branch up to date is met de develop branch. Wanneer de feature afgewerkt is, dan kan de developer een merge uitvoeren om de feature samen te voegen met de develop branch. Zijn feature wordt nu zichtbaar voor andere developers, die dan op hun beurt een rebase zullen moeten uitvoeren op hun feature branch.

Wanneer er een release gepland wordt, kan een tijdelijke release branch in het leven geroepen worden. Deze branch dient om de release voor te bereiden. Eenmaal de release klaar is, wordt deze release branch weer samengevoegd met develop en master. In de master branch wordt dan een tag aangemaakt om de versie aan te duiden, bijvoorbeeld “1.1”.

Duikt er later nog een probleem op in de release en moet er een hotfix geschreven worden, dan kan er een hotfix branch ontstaan uit de master branch. De hotfix wordt dan samengevoegd met zowel develop als master. Op master wordt er weer een nieuwe tag aangemaakt, bijvoorbeeld “1.1.1”.

Door het volgen van deze methode is elke developer verantwoordelijk voor zijn feature branch. Elke developer dient zijn branch up to date te houden met de laatste versie van de applicatie in de develop branch. Elke developer is ook verantwoordelijk om zijn afgewerkte feature terug samen te voegen zonder dat er problemen ontstaan. Dit concept wordt ook Continuous Integration genoemd.

Feature workflow

Features worden ontwikkeld door developers. Dat wil zeggen dat er tegelijkertijd verschillende developers aan hun eigen features kunnen werken. Om dit in goede banen te leiden dient de developer steeds een rebase uit te voeren. Hieronder bevindt zich een gedetailleerde workflow van 2 developers die hun eigen feature ontwikkelen en de conflicten tot een minimum herleiden.

_images/git-flow-2.png

De eerste feature (bovenaan) wordt gecreëerd vanaf de develop branch. Een developer zal verschillende wijzigingen (commits) uitvoeren op deze feature branch. Terwijl maakt een andere developer zijn eigen feature branch, en maakt deze ook enkele wijzigingen. Door “fetch” uit te voeren gaat deze developer na of er wijzigingen aangebracht zijn aan develop. In dit voorbeeld zijn er geen wijzigingen, dus kan deze feature branch terug met de develop samengevoegd worden door middel van een merge. Het is mogelijk dat de developer zelf de merge niet kan uitvoeren, en een zogeheten “pull request (PR)” zal moeten uitvoeren. Deze pull request is een tussenstap voor een merge-actie. Het laat toe om andere developers zijn code te peer-reviewen alvorens deze met develop samengevoegd wordt. We gaan er vanuit dat de Pull Request succesvol was en dat de merge uitgevoerd kon worden.

De feature branch van de andere developer is op dit moment nog steeds open, en deze developer zal bij een fetch te weten komen dat de develop branch aangepast geweest werd. De nieuwe veranderingen in deze develop branch moeten nu samengevoegd worden in zijn feature branch. Dit gebeurt door middel van een “rebase”. Rebase gaat er voor zorgen dat zijn features toegepast (gepatcht) worden op de nieuwe develop branch. Wanneer dit succesvol is, dan kan de developer weer enkele commits uitvoeren en dan uiteindelijk ook een Pull Request indienen om zijn feature samengevoegd te krijgen met develop.

git repository

Git repository software is noodzakelijk om git te kunnen gebruiken. Er zijn verschillende oplossingen beschikbaar, zowel self-hosted en als een service. Enkele bekende oplossingen zijn:

  • Atlassian bitbucket (vroeger ook Stash genoemd - zowel hosted en als een service)
  • Git Server (manueel voor kleine setups)
  • GitHub (service)
  • GitLab (service)
  • Amazon AWS CodeCommit (service)

Testen uitvoeren

Nu dat we de code continu integreren, kunnen we op elke branch testen uitvoeren om na te gaan of de functionaliteit van onze code geen fouten bevat. Lees verder hierover in de sectie Continuous Integration.

_images/contact-in4it.png