Git-substructuur: het alternatief voor de Git-submodule
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.
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 degit 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.
gerelateerd materiaal
Een volledige Git-repository verplaatsen
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.
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.