Versiebeheer is een van de meest onderschatte aspecten van embedded softwareontwikkeling. Toch is het voor elke embedded software engineer een dagelijkse realiteit: code die samenwerkt met hardware, firmware die gebonden is aan specifieke boardversies, en software die bij meerdere klanten tegelijk in productie draait. Zonder een solide versiebeheerstrategie loopt een project snel vast. In dit artikel beantwoorden we de meest gestelde vragen over versiebeheer in embedded projecten, van de basis tot de meer geavanceerde aanpak.
Wat is versiebeheer in embedded softwareprojecten?
Versiebeheer in embedded softwareprojecten is het systematisch bijhouden van alle wijzigingen in broncode, configuratiebestanden en gerelateerde artefacten, zodat teams op elk moment terug kunnen naar een eerdere staat, wijzigingen kunnen traceren en parallel kunnen werken zonder elkaars werk te overschrijven.
In embedded omgevingen gaat versiebeheer verder dan alleen de applicatiecode. Het omvat ook firmwareversies, HAL-lagen (Hardware Abstraction Layer), bootloaders, linkerscripts en soms zelfs de toolchain zelf. De koppeling tussen software en hardware maakt dit complexer dan bij standaard webontwikkeling: een kleine codewijziging kan op de ene boardrevisie prima werken en op een andere volledig falen.
Goede versiebeheersystemen geven een embedded software developer inzicht in wie wat wanneer heeft gewijzigd, en waarom. Dat is niet alleen handig tijdens de ontwikkeling, maar ook essentieel bij het oplossen van bugs in productieomgevingen waar hardware en software nauw verweven zijn.
Waarom is versiebeheer zo belangrijk in de machinebouw?
Versiebeheer is in de machinebouw extra kritisch omdat software en hardware altijd in combinatie worden geleverd. Een machinepark bij een klant kan draaien op verschillende softwareversies, en bij een storing moet een engineer precies weten welke versie op welke machine actief is.
In de praktijk levert dit specifieke uitdagingen op:
- Machines worden soms tien tot twintig jaar gebruikt, waardoor oudere softwareversies lang in de lucht moeten blijven
- Hardwarerevisies van PCBs of modules vereisen bijpassende softwareversies
- Klanten hebben soms eigen certificeringseisen, waardoor software niet zomaar geüpdatet mag worden
- Bugs in productie moeten worden opgelost zonder de stabiele release te destabiliseren
Zonder versiebeheer is het onmogelijk om reproduceerbaar te werken. Dat is in de hightech industrie geen luxe, maar een basisvereiste voor betrouwbare embedded software development.
Welke versiebeheersystemen worden gebruikt in embedded projecten?
In embedded softwareprojecten is Git verreweg het meest gebruikte versiebeheersysteem. Naast Git worden in specifieke industriële omgevingen ook SVN (Subversion) en soms Perforce (Helix Core) toegepast, vooral bij zeer grote codebases of strikte compliancevereisten.
Git heeft de voorkeur vanwege de flexibiliteit van het branchingmodel, de sterke integratie met CI/CD-tooling en de brede ondersteuning binnen de industrie. Voor embedded projecten zijn er wel aanvullende overwegingen:
- Git LFS (Large File Storage) voor grote binaire bestanden zoals firmware images of testdata
- Submodules of subtrees voor het beheren van gedeelde libraries of boardspecifieke code
- Tagging voor het koppelen van softwareversies aan specifieke hardwarerevisies
SVN wordt nog steeds gebruikt in omgevingen waar een centraal, lineair model de voorkeur heeft, bijvoorbeeld bij teams die werken met strikte change management-processen. Perforce is populair in de automotive en semiconductor industrie vanwege de schaalbaarheid bij enorme repositories.
Hoe werkt een branchingstrategie in embedded softwareteams?
Een branchingstrategie in embedded softwareteams bepaalt hoe code wordt georganiseerd over verschillende branches, zodat ontwikkeling, testing en releases parallel kunnen verlopen zonder conflicten. De meest gebruikte aanpak is een variant op Git Flow, aangepast aan de hardware-softwarekoppeling.
Een typische branchingstructuur ziet er als volgt uit:
- Main of master branch: altijd stabiel, bevat alleen goedgekeurde en geteste releases
- Develop branch: integratiebranch waar nieuwe features samenkomen voor de volgende release
- Feature branches: korte branches voor individuele functionaliteiten of bugfixes
- Release branches: stabilisatiebranch voor een specifieke release, inclusief hotfixes
- Hotfix branches: voor kritieke bugs in productie, direct afgeleid van de main branch
In embedded omgevingen voegen teams hier vaak hardwareversie-specifieke branches aan toe. Denk aan een branch voor boardrevisie 1.2 en een aparte voor revisie 2.0, zodat ondersteuning voor oudere hardware niet verloren gaat bij nieuwe ontwikkelingen.
Wat zijn veelgemaakte fouten bij versiebeheer in embedded omgevingen?
De meest voorkomende fout bij versiebeheer in embedded omgevingen is het niet meenemen van de volledige toolchain en buildconfiguratie in het versiebeheersysteem. Hierdoor is een build op een andere machine of op een later moment niet reproduceerbaar, wat in embedded development een ernstig probleem is.
Andere veelgemaakte fouten zijn:
- Binaire bestanden direct committen zonder LFS, waardoor repositories onnodig groot worden
- Geen duidelijke taggingstrategie, waardoor het onduidelijk is welke softwareversie bij welke hardwareversie hoort
- Te lang doorwerken op een feature branch zonder regelmatig te mergen, wat leidt tot grote conflicten
- Commitberichten die alleen beschrijven wat er is veranderd, niet waarom, waardoor context verloren gaat
- Geen scheiding tussen platformonafhankelijke logica en hardwarespecifieke code, waardoor branches moeilijk te beheren zijn
Voor een embedded software engineer is het bijhouden van goede commitberichten en een heldere mappenstructuur geen formaliteit, maar een investering die later uren debuggen bespaart.
Hoe combineer je versiebeheer met CI/CD in embedded projecten?
Versiebeheer combineren met CI/CD in embedded projecten betekent dat elke commit automatisch een buildpipeline triggert die de software compileert, statisch analyseert en indien mogelijk test op gesimuleerde of echte hardware. Dit geeft teams directe feedback over de kwaliteit van elke wijziging.
In de praktijk vraagt dit om een aantal specifieke keuzes:
- Cross-compilatie in de pipeline: de CI-server moet de juiste toolchain hebben voor de doelarchitectuur (ARM, RISC-V, x86)
- Hardware-in-the-loop testing: voor kritieke systemen worden fysieke testopstellingen gekoppeld aan de pipeline
- Statische analyse: tools zoals Cppcheck, Polyspace of SonarQube controleren code automatisch op veelgemaakte fouten
- Artifact management: gegenereerde firmware images worden opgeslagen met versielabels, zodat ze traceerbaar zijn
CI/CD in embedded omgevingen is complexer dan bij webapplicaties, maar de voordelen zijn groot. Teams ontdekken integratieproblemen vroeg, releases worden reproduceerbaar en de koppeling tussen een specifieke commit en de bijbehorende firmware image is altijd traceerbaar. Platforms zoals Jenkins, GitLab CI en GitHub Actions worden in de embedded wereld steeds vaker ingezet voor dit doel.
Hoe wij werken aan versiebeheer in embedded projecten
Bij PROMEXX werken onze engineers dagelijks aan complexe embedded softwareprojecten waarbij versiebeheer, branchingstrategieën en CI/CD geen theorie zijn, maar praktijk. We begrijpen dat goed versiebeheer het verschil maakt tussen een beheersbaar project en een onontwarbare kluwen van codewijzigingen.
Wat wij onze engineers bieden op dit vlak:
- Werken aan inhoudelijk uitdagende projecten bij hightech klanten in de regio Eindhoven en Rotterdam en daarbuiten
- Kennissessies en trainingen over onderwerpen zoals CI/CD, Git-workflows en softwarearchitectuur
- Een omgeving waar je als embedded software developer je vakkennis echt kunt verdiepen
- Projecten waarbij software en hardware hand in hand gaan: van robotica tot machinebesturing en vision-systemen
- Een vaste thuisbasis met persoonlijke begeleiding, ook als je embedded werkt bij een klant
Ben je een ervaren software engineer met affiniteit voor embedded development en wil je werken aan technisch uitdagende projecten? Bekijk dan onze openstaande vacatures en ontdek wat PROMEXX voor jou kan betekenen. Of lees meer over wat wij developers bieden en wat je bij ons kunt verwachten.
Veelgestelde vragen
Hoe begin ik met het opzetten van een versiebeheerstrategie voor een bestaand embedded project zonder versiebeheer?
Begin met het importeren van de huidige codebase in een Git-repository en zorg direct voor een duidelijke mappenstructuur die platformonafhankelijke logica scheidt van hardwarespecifieke code. Stel daarna een eenvoudige branchingstrategie in met minimaal een main- en develop-branch, en tag de huidige staat als een startversie gekoppeld aan de bekende hardwarerevisie. Voeg vervolgens stap voor stap de toolchain, buildconfiguratie en linkerscripts toe aan de repository, zodat builds reproduceerbaar worden. Het is beter om klein te beginnen en de strategie geleidelijk uit te breiden dan te wachten op een 'perfect' moment dat nooit komt.
Hoe koppel ik softwareversies correct aan hardwarerevisies zodat dit altijd traceerbaar blijft?
De meest betrouwbare aanpak is een combinatie van Git-tags en een versietabel in de documentatie of README van de repository, waarin expliciet staat welke softwareversie compatibel is met welke boardrevisie. Gebruik een gestructureerd tagformaat zoals v2.3.1-hw1.2, waarbij het hardware-gedeelte verwijst naar de PCB- of moduleversie. In de firmware zelf kun je de softwareversie en de ondersteunde hardwarerevisie opnemen als constanten, zodat dit ook runtime uitleesbaar is. Dit maakt diagnose in het veld aanzienlijk eenvoudiger wanneer een engineer ter plaatse een machine moet troubleshooten.
Wat is het beste moment om een feature branch te mergen en hoe voorkom ik grote merge-conflicten?
De vuistregel is om feature branches zo kort mogelijk te houden, bij voorkeur niet langer dan een paar dagen tot maximaal twee weken. Merge of rebase regelmatig vanuit de develop-branch naar je feature branch, zodat je continu up-to-date blijft met de wijzigingen van collega's. In embedded projecten helpt het ook om hardwarespecifieke code zoveel mogelijk te isoleren in aparte modules of directories, zodat meerdere engineers parallel kunnen werken zonder elkaars bestanden te raken. Grote conflicten zijn bijna altijd een signaal van te lang wachten met integreren of onvoldoende scheiding van verantwoordelijkheden in de codestructuur.
Hoe ga ik om met versiebeheer van binaire bestanden zoals firmware images, FPGA-bitstreams of CAD-bestanden?
Gebruik Git LFS (Large File Storage) voor binaire bestanden die wél in de repository thuishoren, zoals FPGA-bitstreams of referentie-firmware images. Voor gegenereerde artefacten zoals gecompileerde firmware images is het beter om een dedicated artifact-managementtool te gebruiken, zoals Artifactory of de ingebouwde artifact-opslag van GitLab CI of GitHub Actions, gekoppeld aan een versielabel. CAD-bestanden en schematics horen idealiter in een PDM- of PLM-systeem dat is gesynchroniseerd met de softwareversies via de eerdergenoemde versietabel. Zo houd je de Git-repository beheersbaar en blijven binaire artefacten toch volledig traceerbaar.
Kunnen we CI/CD ook toepassen als we geen fysieke testhardware beschikbaar hebben in de pipeline?
Ja, zelfs zonder fysieke hardware kun je al veel waarde halen uit een CI/CD-pipeline door te focussen op cross-compilatie, statische codeanalyse met tools zoals Cppcheck of SonarQube, en unit tests die draaien op een host-architectuur via een Hardware Abstraction Layer. Door platformonafhankelijke logica te scheiden van hardwarespecifieke drivers, kun je een groot deel van de businesslogica testen zonder echte hardware. Hardware-in-the-loop testing is de ideale volgende stap, maar het is geen vereiste om te starten met geautomatiseerde kwaliteitscontrole. Begin met wat haalbaar is en breid de pipeline uit naarmate het team er meer vertrouwen in krijgt.
Hoe beheer ik langdurige ondersteuning voor oudere softwareversies zonder de doorontwikkeling te blokkeren?
Maak voor elke major release die langdurig ondersteuning vereist een dedicated support-branch aan, bijvoorbeeld support/v1.x, afgeleid van de release-tag op dat moment. Bugfixes voor productieversies worden eerst op de support-branch doorgevoerd en daarna waar relevant cherry-picked naar de develop-branch. Documenteer duidelijk welke branches actief worden onderhouden en tot wanneer, zodat het team bewuste keuzes maakt over waar tijd in wordt geïnvesteerd. In de machinebouw, waar machines tien tot twintig jaar in gebruik zijn, is dit geen uitzondering maar een structurele verantwoordelijkheid die je het beste zo vroeg mogelijk inricht.
Welke aanvullende tools of processen helpen bij het schrijven van betere commitberichten en het bijhouden van context?
Een veelgebruikte aanpak is de Conventional Commits-standaard, waarbij elk commitbericht begint met een type zoals feat, fix of chore, gevolgd door een korte omschrijving en optioneel een uitgebreidere toelichting met de reden achter de wijziging. Koppel commitberichten waar mogelijk aan een ticket of issue in je projectmanagementsysteem, zoals Jira of GitLab Issues, zodat de 'waarom' altijd terugvindbaar is. Tools zoals Commitlint kunnen in de CI-pipeline afdwingen dat berichten aan een afgesproken formaat voldoen. In embedded projecten is het bijzonder waardevol om in het commitbericht te vermelden voor welke hardwarerevisie of configuratie een wijziging bedoeld is, zodat toekomstige engineers direct begrijpen in welke context een keuze is gemaakt.
Gerelateerde artikelen
- Hoe kies je als ervaren software engineer tussen een corporate, detacheerder of specialistisch softwarebedrijf?
- Hoe werkt een embedded software engineer samen met hardware-engineers?
- Hoe stel je een C# ontwikkelomgeving in voor technische projecten?
- Wat leer je als software engineer van werken aan machines in plaats van applicaties?
- Hoe behoud je een vaste thuisbasis terwijl je aan verschillende hightech projecten werkt?