Git of SVN? Hoe koos Nuance Healthcare voor een Git-branching-model?
Matt Shelton
Developer Advocate
Dit is een gastartikel van Matt Shelton van Nuance Healthcare. Dit is het eerste artikel in een serie over de overstap van zijn team van Subversion naar Git, waarom ze dat deden en wat we onderweg tegenkwamen. Matt spreekt ook over dit onderwerp op de Atlassian Summit 2015. Deze serie bevat alles wat hij tijdens zijn toespraak van 30 minuten niet kon zeggen, met meer context.
Achtergrond
Mijn team zit in de gezondheidszorgafdeling van Nuance. We zijn geografisch verdeeld over een aantal kantoren en instellingen aan de oostkust van de VS, en in een kantoor in Poona, India. We ontwikkelen Java-webservices om NLP-oplossingen[1] aan te bieden op de gezondheidszorgmarkt.
Onze serviceklanten zijn voor het grootste deel andere softwarebedrijven in de gezondheidszorg (waaronder wijzelf), zoals leveranciers van EPD-diensten en bedrijven voor gezondheidsanalyse. We verkopen sommige producten rechtstreeks aan ziekenhuizen, en de eindgebruikers van de applicaties variëren van artsen tot medisch factureringspersoneel. 'Normale' mensen zoals jij en ik komen nooit in aanraking met de software die mijn team bouwt.
Ons team heeft een paar keer samengewerkt met productcombinaties voor Application Lifecycle Management. We zijn begonnen met een mix van Rally Enterprise en Seapine TestTrack Pro, hebben ongeveer 14 maanden hard gewerkt met Rational Team Concert en zijn uiteindelijk volledig gemigreerd naar de Atlassian-stack (Jira, Confluence, Bamboo, Crucible en Bitbucket). Vroeger gebruikten we Subversion 1.4/1.5 en onze SCM met een quasi-normale trunk/branch/tag-structuur. We gebruiken Maven sinds mensenheugenis om onze buildprojecten en afhankelijkheden te beheren, en zijn een tijdje geleden overgestapt van Jenkins naar Bamboo voor continue integratie (CI) om gebruik te kunnen maken van nauwere integraties met Jira en zijn flexibele functies voor het bouwen en implementeren van agentmogelijkheden. Alles wat we (nu) gebruiken, bevindt zich met een reden achter de firewall[2].
gerelateerd materiaal
Een volledige Git-repository verplaatsen
Oplossing bekijken
Git leren met Bitbucket Cloud
Git of SVN?
We ondersteunen ongeveer tien afzonderlijke producten, verdeeld over vier productfamilies, en de eigenaren van deze producten strijden altijd om prioriteit en timing. Het is fijn dat er veel vraag is naar ons werk, en dit is zeker geen klacht, maar het vraagt ook dat er met een vreemd tempo wordt gesneden in releases en dat we midden in een sprint van richting moeten veranderen[3].
Ons ontwikkelingsproces voelde soms echt belemmerend aan. Mijn team had regelmatig een gesprek dat ongeveer zo verliep:
Ik: We moeten nu 1.8.0 beschikbaar stellen voor QA voor regressietests, zodat Customer foo volgende week naar de bètaversie kan gaan. Dev: Ik werk nog steeds aan de ABC-123, die in de trunk zit. Die is nog niet klaar. Ik: Foo heeft ABC-123 niet nodig. We zouden het in de volgende release kunnen opnemen. Dev: Maar ik ben er al weken mee bezig. Er is geen duidelijke plek om de branch naartoe te leiden voor release. Ik: Nou, je moet al je wijzigingen maar handmatig pullen. Je hebt ongeveer twee uur de tijd, anders kan QA niet op tijd klaar zijn.
Ik weet het, ik klink als een eikel! Dat was niet mijn bedoeling, en natuurlijk overdrijf ik een beetje om iets duidelijk te maken, maar we moesten echt uitzoeken hoe we de code die op één plek stond tijdelijk eruit konden krijgen, zodat we een release konden stopzetten en die dan terug konden zetten voor de volgende release[4]. En dit gebeurde de hele tijd.
Ik weet dat sommigen van jullie denken 'Subversion ondersteunt ook branches, Matt ...' Dat is absoluut waar, en we hebben ze af en toe gebruikt met SVN 1.4 en 1.5. Vertakking is een prima handeling bij SVN; samenvoegen kan echter lastig zijn. Nu SVN volwassen is geworden, is het zeker beter geworden. Maar we wisten dat er betere opties waren voor ons, dus toen de vraag over SVN of Git opkwam, stapten we over op Git.
Even een kanttekening: we hebben kort gekeken naar de meest recente SVN (destijds 1.8) om te zien of deze sterk genoeg was om onze problemen op te lossen, maar we waren niet helemaal tevreden. Een van onze peergroups heeft een grote Perforce-configuratie en daarin stond veel van wat we nodig hadden, maar ik kon de licentiekosten gewoon niet aan. We hebben ook even naar Mercurial gekeken, maar uiteindelijk was de blootstelling van het bestaande team aan Git voldoende om ons te vertellen dat dat de juiste richting was.
Ik zal er niet omheen draaien: de tools van Atlassian zijn echt geschikt voor teams die Git gebruiken. Andere SCM's werken ook prima. Onze SVN-integratie was voldoende omdat deze ons doorstuurde naar de plaats waar de wijzigingen in een bepaalde userstory zijn aangebracht. De integratiemogelijkheden voor teams die in plaats daarvan Bitbucket[5] gebruiken, zijn zowel sterker als natuurlijker in de interface en ontwikkelervaring van Jira Software, idem met Bamboo.
Nu ik dit weet en nadat ik op Summit 2013 een aantal fantastische demo's had gezien, heb ik het team sterk aangemoedigd om ervoor te gaan. Niemand maakte bezwaar en we hadden al licenties om wijzigingen aan te brengen.
Een Git-branching-model kiezen
Nadat we besloten hadden om deze wijziging door te voeren, was de eerste uitdaging die we hadden om te beslissen welk Git-vertakkingsmodel we voor ons team moesten implementeren. Op de Git-microsite van Atlassian en in deze geweldige presentatie van Summit 2013 wordt gedetailleerder uitgelegd wat een vertakkingsmodel is. In het kort gaat het over hoe je branches in Git kunt gebruiken om je ontwikkelingsworkflow te versterken.
In SVN hadden we een vertakkingsmodel. die ik 'maak er een aan wanneer je er ineens achterkomt dat je er een nodig hebt' noem:
- De nieuwste code zit in de
trunk
. Releases uit de trunk krijgen het nummerA.B.0-{build}
. - Als er een oplossing nodig is voor een release op basis van een trunk (bijv. er is een bug in 1.2.0-64), er wordt een branch aangemaakt en van daaruit brengen we
A.B.C-{build}
releases uit, waarbijC
wordt verhoogd na elke release die de deur uitgaat. Deze branches bestaan voor een bepaaldeA.B
misschien wel nooit en we zouden er zelfs meer dan één aan kunnen maken. - We taggen ook elke release in een directory met tags.
Even terzijde over versies. Toen ik jaren geleden nog maar net bezig was met het beheren van een ontwikkelingsteam, had onze release-technicus een versiebeheersysteem dat ... hoe zal ik dat zeggen ... niet echt intuïtief was. In wezen was elke release een patch op de vorige (A.B.n), ongeacht de plaats waar de patch vandaan kwam. Om uit te zoeken waar iets vandaan kwam en, in bijna alle gevallen, moest je voor de volgorde van release de svn log
bekijken. We hebben de boom toen ter referentie op de muur geplakt. Bovendien zijn onze publicatienummers meestal dingen zoals 3.0, 3.1, 3.5, 4.0, of in wezen iets dat een klant zou verwachten. Onthoud echter dat mijn team webservices bouwt, niet iets dat kant en klaar wordt geleverd. Onze API's zijn een contract. Een paar jaar geleden heb ik ervoor gezorgd dat de uitvoerbare bestanden die mijn team samenstelt, en dus ook de releases, zich zou houden aan de regels voor semantisch versiebeheer. Ik heb een paar keer mijn mannetje moeten staan bij het hoger management, maar nu is duidelijk waarom de regels zijn wat ze zijn, en we hebben niet meer achterom gekeken. Partners waarderen dat soort duidelijkheid.
Ik heb eerder een probleem genoemd waarbij we aan een release werkten (laten we zeggen 1.2.0
) en we zouden een functie hebben die nog in uitvoering was toen we bijna tegen de releasedatum aanzaten. We zouden die code eruit moeten pullen, onze release moeten knippen, naar branches/1.2.1
moeten vertakken en die code dan weer moeten samenvoegen, in de hoop dat in de tussentijd niemand een harde schijf zou laten crashen[6].
Het is lastig om op zichzelf een hele functie uit een gedeelde trunk te verwijderen. Niemand was er blij mee wanneer ze dat moesten doen. svn blame
kan nuttig zijn, net als een sterke diff-tool, maar het blijft vervelend om mee te werken. Ik nam het vaak persoonlijk op, omdat ik het gevoel had dat mijn slechte planning ertoe had geleid dat we niet alles goed voor elkaar hadden voordat we klaar waren met een release[7]. Mijn team heeft hier lang genoeg mee te maken gehad.
Soms corrigeerden we te veel om problemen uit de weg te gaan en vroegen we ontwikkelaars om een paar dagen niets te doen (een virtuele codebevriezing, zeg maar), zodat we de trunk niet vervuilden voor een release.
Dus we wisten dat we in ieder geval functie-branches nodig hadden. Er is een eenvoudig Git-vertakkingsmodel dat van toepassing is: een main-branch voor wat er in prod staat, en het gebruik van functie-branches voor elke functie, bug, enz. Het team moet de samenvoegingsvolgorde beheren om ervoor te zorgen dat wat er naar de main wordt verzonden klaar is voor release. Dit is in wezen hetzelfde als voorheen, met een aantal betere isolatiemogelijkheden, maar we wilden die vrijheid met onze macht kunnen benutten.
In onze omgeving moeten we vaak een paar versies in productie houden en moeten we mogelijk defecten herstellen in een release die 2 tot 3 kleine revisies ouder is dan waar we op dit moment aan werken. Dus naast functie-branches hadden we ook een soort releasebranch of iets dergelijks nodig waarmee we problemen uit eerdere releases konden oplossen. Ze voeren oplossingen aan in langlopende supportbranches en voegen ze vervolgens samen in de branchstroom, zodat een oplossing in alle supportstromen terechtkomt.
Hun model zag er echt goed uit, en we hebben een aantal interacties uitgevoerd met dit model om te zien of het aan onze behoeften zou voldoen. De 'beste app' voor hen is hun doorlopende samenvoeging van een oplossing voor hun ontwikkelafdeling. Hoewel we dit concept goed vonden, stuitten we elke keer dat we het probeerden op een of andere issue met onze Maven-afhankelijkheden. Bovendien konden we in de regel niet garanderen dat we een directe samenvoeging van het werk van de ene versie in de andere wilden. In sommige gevallen moesten we dezelfde oplossing op enigszins verschillende manieren implementeren tussen versies, dus een directe samenvoeging was niet mogelijk.
Een paar leden van het team waren sterk voorstander van een variant van dit model, bekend als 'git-flow'. Git-flow is een verzameling naamgevingsconventies en richtlijnen voor samenvoegingen van branches, geschreven door Vincent Driessen. Dit voelde heel natuurlijk aan voor het team, en we vonden de structuur goed omdat daardoor veel vragen verdwenen waren zoals 'wat moet ik doen als we x moeten doen?'. De antwoorden waren over het algemeen heel voor de hand liggend. In plaats van uit te leggen wat git-flow is, kun je er meer over lezen in de tutorial van Atlassian.
De enige kloof die voor ons overbleef met git-flow was dat we iets moesten doen met die langlopende releases in de productie. Aangezien main zich steeds verder ontwikkelt, konden we de git-flow hotfix-workflow niet gebruiken voor een bugfix uit een vorige release. Aan de andere kant wilden we niet altijd een supportbranch hebben.
Meestal zou een hotfix, waarbij alleen de laatste release in productie wordt gepatcht, voldoende moeten zijn. Support is er alleen als we een stap verder moeten, of als we om een of andere reden de compatibiliteit moeten behouden. Die laatste usecase hebben we verder besproken en criteria bedacht om te kiezen voor een supportbranch in plaats van een hotfix en een kleinere versie-upgrade:
1. Deze code kan niet zomaar worden samengevoegd bij ontwikkeling.
2. De partner/klant kan een wijziging van de interface niet aan die bij de nieuwste release hoort.
3. Er is een interne afhankelijkheid die niet kan worden gewijzigd.[8]
Beide git-flow-uitbreidingspakketten[9] bieden support voor het concept van de support branch dat geen deel uitmaakt van de oorspronkelijke versie van git-flow, maar populair genoeg is geworden om toevoeging te rechtvaardigen.
Git-flow bood een workflow waar we wel mee konden werken, met de toolsupport die we nodig hadden. In het volgende bericht zal ik ingaan op wat er gebeurde toen we het daadwerkelijk probeerden te gebruiken in een POC-project dat we gebruikten om ons ontwikkelingsproces weer te geven. Het was ... iets om van te leren!
[1]: Natuurlijke taalverwerking. WE KUNNEN JE GEDACHTEN LEZEN. (Nee. Niet écht.)
[2]: Er zijn veel dingen aantrekkelijk aan het cloudaanbod van Atlassian, maar we moeten ons voorlopig nog even aan onze servers en data vastklampen. Hoewel we persoonlijk niet veel hoeven te doen met beschermde persoonsgegevens, doet onze software dat wel en het is belangrijk om die zo veilig mogelijk te houden.
[3]: Shhhh ... laat het Ken Schwaber maar niet horen.
[4]: Dat had in ieder geval maar een paar dagen later geweest.
[5]: Voorheen bekend als Stash. Hallo, Atlassian herfst-rebranding!
[6]: Ik weet dat we het altijd uit de vorige commit kunnen pullen. Ik maakte maar een grapje.
[7]: Dat was meestal niet het geval. Over het algemeen was dat omdat het tijdsbestek van iemand anders was verschoven en we snel moesten reageren.
[8]: Dit is een van die dingen waar ik niet op mijn eigen blog op in kan gaan. Vertrouw me maar. Ik heb mijn 'redenen'.
[9]: Het originele pakket van Vincent Driessen wordt niet meer onderhouden. Een nieuwe vertakking wordt echter regelmatig bijgewerkt.
Footnotes
[1]: Natural Language Processing. WE CAN READ YOUR THOUGHTS. (No. Not really.)
[2]: There is a lot that is attractive about Atlassian's cloud offerings, but we need to keep our fingers wrapped tightly around our servers and data for the time being. While we don't personally need to do much with PHI data, our software does and it's important to keep it as secure as possible.
[3]: Shhhh... don't tell Ken Schwaber.
[4]: Which might have only been a few days later anyway.
[5]: Formerly known as Stash. Hello, Atlassian Fall Rebranding!
[6]: I know we could always pull it out of the previous commit. I was kidding.
[7]: This wasn't usually the case - generally it was because someone else's timeframe moved up and we had to react quickly.
[8]: This is one of those things I can't get into on my own blog. Just trust me. "Reasons".
[9]: The original package by Vincent Driessen isn't being maintained any longer. A new fork, however, is regularly updated.
Deel dit artikel
Volgend onderwerp
Aanbevolen artikelen
Bookmark deze resources voor meer informatie over soorten DevOps-teams of voor voortdurende updates over DevOps bij Atlassian.