Submodules: kernconcept, workflows en tips
Nicola Paolucci
Developer Advocate
Door submodules op te nemen als onderdeel van je Git-ontwikkeling, kun je andere projecten in je codebase opnemen, waarbij hun geschiedenis gescheiden blijft maar gesynchroniseerd met die van jou. Het is een handige manier om problemen met de leveranciersbibliotheek en afhankelijkheden op te lossen. Zoals gewoonlijk bij alles wat git
doet, is de aanpak eigenwijs en moedigt deze aan om eerst wat onderzoek te doen voordat die vakkundig kan worden toegepast. Er is al goede en gedetailleerde informatie over submodules
, dus ik herhaal het niet nog eens. Wat ik hier ga doen, is een aantal interessante dingen met je delen die je zullen helpen om deze functie optimaal te benutten.
Inhoudsopgave
gerelateerd materiaal
Een volledige Git-repository verplaatsen
Oplossing bekijken
Git leren met Bitbucket Cloud
Kernconcept
Laat me eerst een korte uitleg geven over een kernconcept van submodules, wat ze makkelijker bruikbaar maakt.
Submodules worden bijgehouden op basis van de exacte commit die is gespecificeerd in het bovenliggende project, niet in een branch, referentie of andere symbolische referentie.
Ze worden nooit automatisch bijgewerkt wanneer de door de submodule gespecificeerde repository wordt bijgewerkt, alleen wanneer het bovenliggende project zelf wordt bijgewerkt. Zoals heel duidelijk verwoord in het eerder genoemde hoofdstuk over Pro Git:
Wanneer je wijzigingen aanbrengt en vastlegt in die subdirectory [submodule], merkt het superproject dat de HEAD daar is gewijzigd en registreert het de exacte commit waar je op dit moment mee bezig bent. Op die manier kunnen anderen, wanneer ze dit project klonen, de omgeving exact opnieuw creëren.
Of met andere woorden:
[...] git-submodules [...] zijn statisch. Heel statisch. Je houdt specifieke commits bij met git-submodules, niet met branches, niet met referenties, één commit. Als je commits toevoegt aan een submodule, weet het bovenliggende project dat niet. Als je een aantal vertakkingen van een module hebt, maakt dat voor de git-submodules niets uit. Je hebt één externe repository en je wijst naar één commit. Totdat je het bovenliggende project bijwerkt, verandert er niets.
Mogelijke workflows
Door dit kernconcept te onthouden en erover na te denken, kun je begrijpen dat die submodule
sommige workflows goed ondersteunt en andere minder optimaal. Er zijn minstens drie scenario's waarin submodules een redelijke keuze zijn:
-
Als een component of subproject te snel verandert of als er komende wijzigingen de API defect maken, kun je voor je eigen veiligheid de code aan een specifieke commit vastkoppelen.
-
Als je een component hebt die niet vaak wordt bijgewerkt en je dit wilt bijhouden als leveranciersafhankelijkheid. Ik doe dit bijvoorbeeld voor mijn vim-plug-ins.
-
Wanneer je een deel van het project delegeert aan een externe partij en je hun werk op een bepaald moment of in een specifieke release wilt integreren. Nogmaals, dit werkt als er niet te vaak updates zijn.
Met dank aan Finch voor de goed toegelichte scenario's.
Handige binnenkomende tips
De infrastructuur van de submodule is krachtig en maakt een nuttige scheiding en integratie van codebases mogelijk. Er zijn echter eenvoudige handelingen waarvoor geen gestroomlijnde procedure of krachtige ondersteuning van de gebruikersinterface voor opdrachtregels vereist is.
Als je in je project git-submodules gebruikt, heb je hiermee te maken gehad of gaat dat gebeuren. Als het gebeurt, zul je de oplossing moeten opzoeken. Keer op keer. Laat me je onderzoekstijd besparen: gebruik Instapaper, Evernote of ouderwets een bladwijzer voor deze pagina (:D:D) en je bent voorlopig onder de pannen.
Dit is wat ik voor je heb:
Hoe wissel je een git-submodule met je eigen vertakking
Dit is een veel voorkomende workflow: je begint het project van iemand anders als submodule te gebruiken, maar na een tijdje merk je dat het nodig is om het aan te passen en het zelf bij te werken. Daarom wil je het project vertakken en de submodule vervangen door je eigen vertakking. Hoe doe je dat?
De submodules worden opgeslagen in .gitmodules
:
$ cat .gitmodules [submodule "ext/google-maps"] path = ext/google-maps url = git://git.naquadah.org/google-maps.git
Je kunt de URL gewoon bewerken met een teksteditor en dan het volgende uitvoeren:
$ git submodule sync
Hiermee wordt .git/config
bijgewerkt. die een kopie bevat van deze lijst met submodules (je kunt ook gewoon het relevante [submodule]
-gedeelte van .git/config
handmatig bewerken).
Hoe verwijder ik een submodule?
Het is een vrij algemene behoefte, maar de procedure is nogal ingewikkeld. Om een submodule te verwijderen, moet je het volgende doen:
1. Verwijder de relevante regel uit het bestand .gitmodules
.
2. Verwijder het relevante gedeelte uit .git/config
.
3. Voer git rm --cached path_to_submodule
uit (geen schuine streep erachter).
4. Commit en verwijder de submodule-bestanden die nu niet meer worden gevolgd.
Hoe integreer ik een submodule weer in mijn project?
Of met andere woorden, hoe maak ik een git-submodule ongedaan? Als je alleen de code van je submodule in de hoofdrepository wilt plaatsen, hoef je alleen maar de submodule te verwijderen en de bestanden opnieuw toe te voegen aan de hoofdrepo:
1. Verwijder de referentie naar de submodule uit de index, maar bewaar de bestanden:
git rm --cached submodule_path (no trailing slash)
2. Verwijder het .git-modules-bestand of als je meer dan één submodule hebt, bewerk dan dit bestand door de submodule uit de lijst te verwijderen:
git rm .gitmodules
3. Verwijder de .git map met metagegevens (zorg dat je er een back-up van hebt):
rm -rf submodule_path/.git
4. Voeg de submodule
toe aan de hoofdindex van de repository:
git add submodule_path git commit -m "remove submodule"
OPMERKING: De hierboven beschreven procedure is destructief voor de geschiedenis van de submodule. In gevallen waarin je een congruente geschiedenis van je submodules wilt behouden, moet je een slimme 'merge' doorlopen. Voor meer informatie verwijs ik je naar deze zeer volledige referentie voor Stack Overflow.
Hoe kun je veranderingen in submodules negeren?
Soms raken je submodules
vanzelf vervuild
. Als je bijvoorbeeld git-submodules
gebruikt om je vim-plug-ins te volgen, kunnen ze lokale bestanden zoals helptags
genereren of wijzigen. Helaas gaat git-status je dan steeds wijzen op die veranderingen, ook al ben je er helemaal niet in geïnteresseerd en ben je niet van plan ze te committen.
De oplossing is heel eenvoudig. Open het bestand .gitmodules
in de hoofdmap van je repository en voeg vervolgens voor elke submodule die je wilt negeren ignore = dirty
toe, zoals in dit voorbeeld:
[submodule ".vim/bundle/msanders-snipmate"] path = .vim/bundle/msanders-snipmate url = git://github.com/msanders/snipmate.vim.git ignore = dirty
Met dank aan Nils voor de geweldige uitleg.
Gevaarzone! Valkuilen bij interactie met remotes
Zoals wordt aangegeven in de Git Submodule Tutorial op kernel.org, zijn er een paar belangrijke dingen waar je op moet letten bij interactie met je externe repository's.
Ten eerste moet je de wijziging in de submodule altijd publiceren voordat je de wijziging publiceert in het superproject dat ernaar verwijst. Dit is van cruciaal belang omdat het anderen kan verhinderen de repository te klonen.
Ten tweede moet je altijd onthouden dat je al je wijzigingen moet committen voordat je git submodule update
uitvoert, omdat wijzigingen worden overschreven als deze er zijn!
Conclusies
Gewapend met deze notities zou je in staat moeten zijn om veelvoorkomende terugkerende workflows aan te pakken die zich voordoen bij het gebruik van submodules. In een volgende post zal ik schrijven over alternatieven voor git submodule
.
Volg mij @durdn en het geweldige @Bitbucket-team voor meer DVCS-details.
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.