Git submodule HOWTO

Jeg har tidligere i dette tidligere blog-indlæg åbnet diskussionen om hvordan man med versionskontrolsystemet Git kan håndtere bånd mellem afhængige software-projekter. Jeg har sidenhen arbejdet bla. med “git submodule” og jeg er vist kommet et godt stykke rundt om det. Derfor vil jeg i dette blogindlæg præsentere, hvordan det virker og hvad der ikke virker.

Grundideen er at jeg har et Git-projekt “Top.git”, som afhænger af et eller flere under-projekter “Sub1.git”, “Sub2.git” osv. Underprojekterne vil oftest være software-stumper, som er genbrugte fra andre projekter eller opsætningsfiler, som andre skal kunne tage ud uafhængigt af “hovedprojekt”.

Vi kan antage at hver af Git-projekterne “Top.git”, “Sub1.git”, “Sub2.git”... osv er lagt direkte i filsystemet eller på en Git-server. Nedenfor antager jeg ved kloning at projekterne ligger i /storage/git/, og for sjov kan vi placere “Sub1” som katalog lige neden under “Top1”. Det kan placeres hvor det skal være indenfor Top1-katalog-strukturen.

Den første opsætning

Jeg har tilføjet kommentarer efter Git-kommandoerne

  $ git clone /storage/git/Top.git  # Check Top ud
  $ cd Top1   # Gå ind i Top/
  $ git submodule add /storage/git/Sub1.git      #  Check Sub1 ud under Top           
  $ git add Sub1   # Versionskontroller Sub1 indenfor Top 
  $ git add .gitmodules   # Da det er første submodule så skal vi tilføje denne fil
  $ git commit -m "Tilføjer Sub1" .gitmodules Sub1    
  $ git push   # Skub ændringen afsted

Efterfølgende kloning

Den næste person som gerne vil klone “Top” kan (næsten) automatisk få “Sub1” underprojektet med

  $ git clone /storage/git/Top.git  # Check Top ud
  $ cd Top1   # Gå ind i kataloget Top
  $ git submodule init   # Register alle submodulerne - køre
  $ git submodule update   # Hent submodulerne

Jeg forstod i starten ikke, hvorfor man design-mæssigt har indført opdelingen mellem “git submodule init” og “git submodule update”.
Forklaringen er den snedige, at hvis man har Linux-folk og Windows-folk, der arbejder sammen i samme Windows-katalogs-struktur, så kan Linux-brugeren rette stier i Top/.git/submodule efter “git submodule init” så stierne passer med Linux. Se mere i her.

Opdatering af versionen af Sub1 i Top

Mens man har arbejdet på Top kan det være at der er kommet ny version af Sub1, som skal integreres. Jeg antager at Sub1 versionen er lavet i “master”-grenen. En nem metode er som følger

  $ cd Top/Sub1/  # Gå ned i Sub1 kataloget
  $ git checkout master # Se nedenfor!
  $ git pull  # Hent nyeste version af Sub1 på master grenen
  $ cd ..
  $ git commit -m “Opdatering af Sub1” Sub1 # Register den nye version
  $ git push 

Når man bruger “git submodule” vil undermodulerne oftest ende som en “detached head”, dvs. at de ikke er på en gren (branch). Man kan se dette med “git branch”. Derfor har jeg vænnet mig til at lave “git checkout” til den gren, jeg skal bruge.

Droppe en Test-opdatering af versionen af Sub1 i Top

Nogle gange finder man en "dårlig" version af nyeste "Sub1", som man har testet, og dernæst skal man gerne vende tilbage til den

  $ cd Top/Sub1/  # Gå ned i Sub1 kataloget
  $ git checkout master
  $ git pull  # Register nyeste version af Sub1 på master grenen

Hvis den nye version af "Sub1" er skidt, så kan vi droppe den igen fra "Top"-kataloget:

  $ cd Top
  $ git submodule update Sub1

Har man auto-genereret kode i Sub1 f.eks. object-filer fra make eller lign. så skal de lige smides væk.

Problemer med Git submodule

Det bør nævnes, at der er solide argumenter for IKKE at bruge “git submodule” som diskuteret bla. her.

Jeg har selv anvendt “git submodule” de sidste par måneder og er glad for det, men det er ret klart for mig at det fungerer klart bedst, når det er få personer, som opdaterer i versionen af undermodulerne i hovedprojektet. Og “git submodule” er dårligt egnet til at håndtere projekter, hvor undermodulerne skal opdateres hele tiden - såsom hvis det er lige så mange ændringer i “Sub1” som i “Top”.
Men som sagt, er ændrings-hastigheden i undermodulerne en del under ændrings-hastigheden i hovedprojektet så fungerer det fint.

Jeg regner med at gå tilsvarende ind i de andre metoder til at håndtere afhængige Git-projekter og blogge om dette senere.

/pto

P.S. I er meget velkomne til at kommentere og kritisere ovenstående. Jeg prøver at lære alle detaljer :-)

Kommentarer (9)
sortSortér kommentarer
  • Ældste først
  • Nyeste først
  • Bedste først
Arne Jørgensen

Hvis man ikke har særlig behov for at opdele "git submodule init" og "git submodule update" - og man i øvrigt har submodules inde i submodules så bruger jeg følgende med succes (de få gange jeg har behovet):

git submodule update --init --recursive
  • 1
  • 0
Peter Mogensen

Det overraskede mig lidt at se siden med argumenter imod at bruge git submodule afslutte med noget der minder om en anbefaling af SVN externals.
Vores konklussion, efter at have sloges med SVN external på 117 måder, var ellers at det var af det onde. - og mange af problemerne følger med til git submodules.

Man skal simpelthen overveje meget grundigt om det er noget man ikke kan løse på anden måde. F.eks. som eksterne versionerede libraries og angive afhængigheder af dem.
Jeg bruger kun git submodule et sted og det er simpelthen fordi den aktuelle debian-pakkes build system forventer at finde et andet projekt som et subdir et sted i kilde-teksten. Det er der ikke nogen teknisk grund til at den gør ud over den måde debian-pakken gerne vil fordele indholdet mellem forskellige binære pakker. Havde jeg selv designet debian-pakken havde jeg nok kraftigt overvejet ikke at blande de to projekter sammen i samme pakke.

  • 1
  • 0
Jesper Louis Andersen
  • 2
  • 0
Frank Kjul Larsen

Jamen så lad os da høre hvad du/I ellers vil anbefale.

Det er for nemt at sige at noget som trods alt prøver at løse et behov ikke dur og at man skal bruge "noget andet" uden at komme nærmere ind på hvad det er eller kan være.

Jeg er bruger af og prøver at promovere brugen af SVN externals "i mine omgivelser". Jeg vil hjertens gerne høre om (gode) alternativer.

  • 0
  • 0
Steffen Postas

Den næste person som gerne vil klone “Top” kan (næsten) automatisk få “Sub1” underprojektet med

Dette kan faktisk gøres langt mere effektivt ved blot at sige

$ git clone /storage/git/Top.git --recursive

Således bliver alle submodules også klonet og checket ud, såvel som submodule submodules.

  • 0
  • 0
Log ind eller Opret konto for at kommentere
IT Company Rank
maximize minimize