Close

Git-substructuur: het alternatief voor de Git-submodule

Headshot van Nicola Paolucci
Nicola Paolucci

Developer Advocate


Het internet staat vol met artikelen over waarom je geen Git-submodules zou moeten gebruiken. Hoewel submodules nuttig zijn voor een paar toepassingen, hebben ze wel verschillende nadelen.

Zijn er alternatieven? Het antwoord is ja! Er zijn (minstens) twee hulpmiddelen die kunnen helpen bij het bijhouden van de geschiedenis van softwareafhankelijkheden in je project, waarbij je Git kunt blijven gebruiken:

  • Git subtree
  • Google repo

In dit artikel kijken we naar git subtree en laten we zien waarom dit een verbetering is — zij het niet perfect — ten opzichte van git submodule.

Wat is git subtree en waarom zou ik dat gebruiken?


Met git subtree kun je de ene repository in een andere opslaan als submap. Het is een van de verschillende manieren waarop Git-projecten projectafhankelijkheden kunnen beheren.

Diagram van de subtree voor/na Git

Waarom zou je git subtree overwegen?

  • Het beheer van een eenvoudige workflow is eenvoudig;
  • Oudere versies van Git worden ondersteund (zelfs ouder dan v1.5.2);
  • De code van het subproject is direct beschikbaar nadat de kloon van het superproject is voltooid;
  • De git subtree vereist niet dat gebruikers van je repository iets nieuws leren. Ze kunnen negeren dat je de git subtree gebruikt om afhankelijkheden te beheren;
  • De git subtree voegt geen nieuwe metagegevensbestanden toe zoals git submodule dat doet (d.w.z.gitmodule);
  • De inhoud van de module kan worden gewijzigd zonder dat je ergens anders een aparte kopie van de afhankelijkheid in de repository moet hebben.

Nadelen (maar volgens ons zijn deze grotendeels aanvaardbaar):

  • Je moet iets leren over een nieuwe samenvoegingsstrategie (d.w.z. de git subtree);
  • Het is iets ingewikkelder om stroomopwaarts bij te dragen aan de code van subprojecten;
  • De verantwoordelijkheid om super- en subprojectcode niet te combineren in commits ligt bij jou.
Databases
gerelateerd materiaal

Een volledige Git-repository verplaatsen

Logo Bitbucket
Oplossing bekijken

Git leren met Bitbucket Cloud

De git subtree gebruiken


git subtree is sinds mei 2012 beschikbaar als stockversie van Git v1.7.11 en hoger. De versie die door homebrew op OSX wordt geïnstalleerd, heeft al een goed verbonden substructuur, maar op sommige platformen moet je misschien de installatie-instructies volgen.

Hier is een canonisch voorbeeld van het traceren van een vim-plug-in met behulp van git subtree.

De snelle manier, zonder tracering op afstand

Wil je gewoon een paar oneliners om te knippen en te plakken, lees dan deze alinea. Voeg eerst een git subtree toe aan een map met een opgegeven voorvoegsel:

git subtree add --prefix .vim/bundle/tpope-vim-surround https://bitbucket.org/vim-plugins-mirror/vim-surround.git main --squash

(Het is gebruikelijk om niet de volledige geschiedenis van het subproject op te slaan in je hoofdrepository. Mocht je deze toch willen bewaren, laat dan de markering -squash weg.)

De bovenstaande opdracht levert deze output op:

git fetch https://bitbucket.org/vim-plugins-mirror/vim-surround.git main
warning: no common commits
remote: Counting objects: 338, done.
remote: Compressing objects: 100% (145/145), done.
remote: Total 338 (delta 101), reused 323 (delta 89)
Receiving objects: 100% (338/338), 71.46 KiB, done.
Resolving deltas: 100% (101/101), done.
From https://bitbucket.org/vim-plugins-mirror/vim-surround.git
* branch main -} FETCH_HEAD
Added dir '.vim/bundle/tpope-vim-surround'

Zoals je kunt zien, wordt hier een merge commit geregistreerd door de hele geschiedenis van de vim-surround-repository samen te voegen in één repository:

1bda0bd [3 minutes ago] (HEAD, stree) Merge commit 'ca1f4da9f0b93346bba9a430c889a95f75dc0a83' as '.vim/bundle/tpope-vim-surround' [Nicola Paolucci]
ca1f4da [3 minutes ago] Squashed '.vim/bundle/tpope-vim-surround/' content from commit 02199ea [Nicola Paolucci]

Als je na een tijdje de code van de plug-in wilt bijwerken vanuit de upstream-repository, kun je gewoon een git subtree ophalen:

git subtree pull --prefix .vim/bundle/tpope-vim-surround https://bitbucket.org/vim-plugins-mirror/vim-surround.git main --squash

Dit werkt erg snel en moeiteloos, maar de opdrachten zijn nogal lang en moeilijk te onthouden. We kunnen de opdrachten korter maken door het subproject als extern project toe te voegen.

Het subproject toevoegen als extern project

Door de substructuur als extern project toe te voegen, kunnen we er in verkorte vorm naar verwijzen:

git remote add -f tpope-vim-surround https://bitbucket.org/vim-plugins-mirror/vim-surround.git

We kunnen nu de substructuur toevoegen (zoals eerder), maar in korte vorm naar de externe locatie verwijzen:

git subtree add --prefix .vim/bundle/tpope-vim-surround tpope-vim-surround main --squash

De opdracht om het subproject op een later tijdstip bij te werken wordt:

git fetch tpope-vim-surround main
git subtree pull --prefix .vim/bundle/tpope-vim-surround tpope-vim-surround main --squash

Stroomopwaarts weer bijdragen

We kunnen onze oplossingen nu vrij aan het subproject toevoegen in onze lokale werkmap. Wanneer het tijd is om een bijdrage aan het upstream-project te leveren, moeten we het project vertakken en het als een andere externe locatie toevoegen:

git remote add durdn-vim-surround ssh://git@bitbucket.org/durdn/vim-surround.git

Nu kunnen we de opdracht subtree push gebruiken, zoals:

git subtree push --prefix=.vim/bundle/tpope-vim-surround/ durdn-vim-surround main
git push using: durdn-vim-surround main
Counting objects: 5, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 308 bytes, done.
Total 3 (delta 2), reused 0 (delta 0)
To ssh://git@bitbucket.org/durdn/vim-surround.git
02199ea..dcacd4b dcacd4b21fe51c9b5824370b3b224c440b3470cb -} main

Daarna zijn we klaar en kunnen we een pull-aanvraag openen voor de onderhouder van het pakket.

Kan ik dit doen zonder de opdracht git subtree te gebruiken?

Ja! Dat kan zeker. git subtree is anders dan de strategie voor het samenvoegen van substructuren. Je kunt nog steeds de samenvoegingsstrategie gebruiken, zelfs als git subtree om de een of andere reden niet beschikbaar is. Dat moet je zo aanpakken.

Voeg de afhankelijkheid toe als een eenvoudige git remote:

git remote add -f tpope-vim-surround https://bitbucket.org/vim-plugins-mirror/vim-surround.git

Voordat we de inhoud van de afhankelijkheid in de repository lezen, is het belangrijk om een samenvoeging vast te leggen, zodat we de volledige structuurgeschiedenis van de plug-in tot nu toe kunnen volgen:

git merge -s ours --no-commit tpope-vim-surround/main

Dat levert het volgende op:

Automatic merge went well; stopped before committing as requested

Vervolgens lazen we de inhoud van het nieuwste structuurobject in de repository voor plug-ins in onze werkmap, klaar om te worden vastgelegd:

git read-tree --prefix=.vim/bundle/tpope-vim-surround/ -u tpope-vim-surround/main

Nu kunnen we een commit maken (deze wordt een merge die de geschiedenis bewaart van de structuur die we hebben gelezen):

git ci -m"[subtree] adding tpope-vim-surround"
[stree 779b094] [subtree] adding tpope-vim-surround

Als we het project willen bijwerken, kunnen we nu een pull uitvoeren met behulp van de git subtree-samenvoegingsstrategie:

git pull -s subtree tpope-vim-surround main

Git subtree is een geweldig alternatief


Na een tijdje git-submodules te hebben gebruikt, zul je zien dat git subtree veel problemen met de git-submodule oplost. Zoals gewoonlijk is er bij alles wat met Git te maken heeft, een leercurve om de functie optimaal te benutten.

Volg me op Twitter @durdn voor meer dingen over Git en dergelijke. En raadpleeg ook Atlassian Bitbucket als je op zoek bent naar een goed hulpmiddel om je Git-repo's te beheren.

Update: na de publicatie van dit artikel schreef ik ook een artikel over de kracht van de Git subtree.

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
Volgend onderwerp

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