Close

Git en projectafhankelijkheden

Headshot van Nicola Paolucci
Nicola Paolucci

Developer Advocate

Denk na over de volgende vragen. Hoe ga je om met projectafhankelijkheden met git? Ons project bestaat uit meerdere onderling afhankelijke repository's. Op dit moment beheren we die met svn:externals. Wat is de beste manier om die met git te verwerken? Hoe verdeel je een zeer grote repository in kleinere componenten met behulp van git? Dit zijn enkele voorbeelden van de meest gestelde vragen die we kregen tijdens de Europese etappe van onze recente Getting Git Right-tournee.

Dit onderwerp lijkt een groot pijnpunt te zijn voor veel softwareteams die git gebruiken. Daarom zal ik in dit artikel proberen om wat licht op het probleem te werpen.

Het is duidelijk dat projectafhankelijkheden en de infrastructuur van builds twee met elkaar verweven gebieden zijn, en zelfs intern bij Atlassian ontstond er een discussie over de 'toekomst van builds'.

Het hebben van afzonderlijke repository's in plaats van één repository kan sommige dingen moeilijker maken. Maar het is een relatief natuurlijke (en soms verplicht) stap in de evolutie van een softwareproject minstens twee belangrijke redenen: langere buildtijden en gedeelde afhankelijkheden tussen projecten.

Denk na over de volgende vragen. Hoe ga je om met projectafhankelijkheden met git? Ons project bestaat uit meerdere onderling afhankelijke repository's. Op dit moment beheren we die met svn:externals. Wat is de beste manier om die met git te verwerken? Hoe verdeel je een zeer grote repository in kleinere componenten met behulp van git? Dit zijn enkele voorbeelden van de meest gestelde vragen die we kregen tijdens de Europese etappe van onze recente Getting Git Right-tournee.

Dit onderwerp lijkt een groot pijnpunt te zijn voor veel softwareteams die git gebruiken. Daarom zal ik in dit artikel proberen om wat licht op het probleem te werpen.

Het is duidelijk dat projectafhankelijkheden en de infrastructuur van builds twee met elkaar verweven gebieden zijn, en zelfs intern bij Atlassian ontstond er een discussie over de 'toekomst van builds'.

Het hebben van afzonderlijke repository's in plaats van één repository kan sommige dingen moeilijker maken. Maar het is een relatief natuurlijke (en soms verplicht) stap in de evolutie van een softwareproject minstens twee belangrijke redenen: langere buildtijden en gedeelde afhankelijkheden tussen projecten.


Schilderen met grove kwasten: richtlijnen en suboptimale oplossingen


Dus terug naar de vraag: Hoe volg en beheer je projectafhankelijkheden met git?

Indien mogelijk, doe je dat niet!

Grapjes terzijde, laat me eerst in grote lijnen antwoorden en daarna dieper hierop ingaan. Realiseer je alsjeblieft dat er geen wondermiddel bestaat (in git of anderszins) waarmee alle problemen die verband houden met projectafhankelijkheden pijnloos kunnen worden opgelost.

Als een project eenmaal groter is dan een bepaalde omvang, is het verstandig om het op te splitsen in logische componenten, maar wacht niet tot je meer dan 100 miljoen regels code in één repository hebt voordat je dat doet. Het volgende zijn dus slechts richtlijnen, zodat je je eigen aanpak kunt bedenken.

Git-logo
gerelateerd materiaal

Git installeren

Logo Bitbucket
Oplossing bekijken

Git leren met Bitbucket Cloud

Eerste keuze: gebruik een geschikte build-/afhankelijkhedentool in plaats van git


Een hulpmiddel voor het beheer van onderlinge relaties is op dit moment mijn aanbevolen oplossing om de groeipijnen en de buildtijden van omvangrijke projecten aan te pakken.

Houd je modules gescheiden in afzonderlijke repository's en beheer hun onderlinge afhankelijkheid met een tool die daarvoor speciaal ontwikkeld is. Er is er een voor (bijna) elke bestaande technologiestack. Enkele voorbeelden:

  • Maven (of Gradle) als je Java gebruikt
  • Npm voor node-apps
  • Bower, Component.io, enz. als je Javascript gebruikt (bijgewerkt!)
  • Pip en requirements.txt als je Python gebruikt
  • RubyGems, Bundler als je Ruby gebruikt
  • NuGet voor .NET
  • Ivy (of een aangepaste CMake-actie) voor C++ (bijgewerkt!)
  • CocoaPods voor Cocoa iOS-apps
  • Composer of Phing voor PHP (toegevoegd!)
  • In Go is de build/afhankelijkheden-infrastructuur in zekere mate ingebouwd in de taal (hoewel er is gewerkt aan een completere oplossing, zie godep) Voor onze Git-server Bitbucket Server gebruiken we zowel Maven als Bower. Tijdens de build zal de tool naar keuze de juiste versies van de afhankelijkheden pullen, zodat je hoofdproject kan worden gebouwd. Sommige van deze tools hebben beperkingen en maken veronderstellingen die niet optimaal, maar wel bewezen en haalbaar zijn.

De pijn van het splitsen van je project

Simpel gezegd, aan het begin van een project zit alles in één build. Maar naarmate het project groeit, kan dat ertoe leiden dat je build te traag wordt. Op dat moment heb je 'caching' nodig, en dat is waar beheer van onderlinge relaties een rol speelt. Dit betekent trouwens dat submodules (zie hieronder) zich heel goed lenen voor bijvoorbeeld dynamische talen. In feite denk ik dat de meeste mensen zich op een gegeven moment zorgen moeten maken over de buildtijden. Daarom moet je een tool voor het beheer van onderlinge relaties gebruiken.

Componenten opsplitsen in afzonderlijke repository's brengt nogal wat pijn met zich mee. In willekeurige volgorde:

  • Om een component te wijzigen is een release vereist
  • Kost tijd en kan om veel stomme redenen mislukken
  • Het voelt stom voor kleine veranderingen
  • Het vereist het handmatig opzetten van nieuwe builds voor elk component
  • Belemmert de vindbaarheid van repository's
  • Refactoring wanneer niet de hele bron beschikbaar is in één repository
  • In sommige configuraties (zoals de onze) is voor het updaten van API's een mijlpaalrelease van het product vereist, en vervolgens de plug-in, en dan weer het product. We hebben waarschijnlijk een paar dingen gemist, maar je snapt het wel. Een perfecte oplossing voor het probleem is verre van beschikbaar.

Tweede keuze: git-submodule gebruiken


Als je geen afhankelijkhedentool kunt of wilt gebruiken, heeft git de mogelijkheid om submodules te verwerken. Submodules kunnen handig zijn, vooral voor dynamische talen. Maar ze zullen je niet noodzakelijkerwijs behoeden tegen langzame buildtijden. Ik heb er al enkele richtlijnen en tips over geschreven en ik heb ook alternatieven onderzocht. Het internet in het algemeen heeft er ook argumenten tegen.

1:1 match tussen svn:external en git

MAAR! Als je op zoek bent naar een 1-op-1 match tussen svn:externals en git, dan wil je submodules gebruiken om ervoor te zorgen dat de submodules alleen releasebranches bijhouden en geen willekeurige commits.

Derde keuze: gebruik andere tools voor builds en cross-stack afhankelijkheden


Je zult niet altijd plezier beleven aan een project dat volledig uniform is en dat met één tool gebouwd en samengesteld kan worden. Sommige mobiele projecten zullen bijvoorbeeld moeten schakelen tussen Java- en C++-afhankelijkheden, of eigendomsrechtelijke tools moeten gebruiken om assets te genereren. Voor complexere situaties kun je git uitbreiden met een extra laag er bovenop. Een goed voorbeeld op dit gebied is de repo van Android.

Andere buildtools die het ontdekken waard zijn:

Conclusies en verder lezen


Charles O'Farrell heeft zorgvuldig meer artikelen over de infrastructuur van builds (en Maven) voorgesteld, die zeer interessant om over na te denken:

Ik wil afsluiten met dit uitstekende citaat uit het laatste artikel hierboven. Ook al gaat het om Maven, het kan evengoed worden toegepast op andere build- en afhankelijkhedentools:

"Een cache doet niets anders dan dingen versnellen. Je zou een cache volledig kunnen verwijderen en het omringende systeem zou hetzelfde blijven werken, alleen langzamer. Een cache heeft ook geen bijwerkingen. Het maakt niet uit wat je in het verleden met een cache hebt gedaan, een bepaalde zoekopdracht naar de cache zal in de toekomst dezelfde waarde retourneren naar dezelfde zoekopdracht.

De Maven-ervaring is heel anders dan wat ik beschrijf! Maven-repository's worden gebruikt als caches, maar zonder de eigenschappen van caches. Als je iets vraagt in een Maven-repository, maakt het erg uit wat je in het verleden hebt gedaan. Het retourneert het meest recente ding dat je erin hebt gestopt. Het kan zelfs mislukken, als je om iets vraagt voordat je het erin stopt."

Nicola Paolucci

Nicola is an all-round hacker who loves exploring and teaching bleeding edge technologies. He writes and talks about Git, development workflows, code collaboration and more recently about Docker. Prior to his current role as Developer Instigator at Atlassian he led software teams, built crowd sourcing applications for geo-spacial data, worked on huge e-commerce deployments. Little known facts about Nicola: he gesticulates a lot while speaking (being Italian), lives in Amsterdam and rides a Ducati.


Deel dit artikel

Aanbevolen artikelen

Bookmark deze resources voor meer informatie over soorten DevOps-teams of voor voortdurende updates over DevOps bij Atlassian.

Mensen die samenwerken met een muur vol tools

Bitbucket-blog

Toelichting DevOps

DevOps-leertraject

Demo Den Feature-demo's met Atlassian-experts

Hoe Bitbucket Cloud werkt met Atlassian Open DevOps

Meld je aan voor onze DevOps-nieuwsbrief

Thank you for signing up