Šta su git submoduli?
Submoduli su projekti (najčešće neke biblioteke) koji su ubačeni u neki drugi projekat, nakon čega su u tom tzv. “glavnom” projektu dostupni svi fajlovi submodula. Git subdmoduli nam omogućavaju da koristimo dva ili više repozitorijuma kao da su jedno. Svaki repozitorijum održava svoju zasebnu istoriju promena pa se čak subdmoduli ažuriraju nezavisno od glavnog repozitorijuma. Kada klonirate ili povučete repozitorijum sa submodulom, glavni repozitorijum dobija samo vezu do mesta odakle će “povući” kod submodul-a.
Submoduli su korisni ako u jednom git repozitorijumu imate kod ili sadržaj koji želite da koristite u više drugih projekata kojima upravlja git, ali ipak želite da istorija promena ostane odvojena. Na primer, možda koristite biblioteku koja je u aktivnom razvoju a morate da razvijete svoj kod aplikacije zajedno sa svim promenama submodula.
Kada dodate subdmodul u Git, vi ne dodajete ceo kod subdmodula u glavni repozitorijum, već dodajete samo informacije o subdmodulu. Ove informacije opisuju na koji komit subdmodula se pokazuje. Zbog toga kod subdmodula neće doći do ažuriratanja kada se ažurira repozitorijum glavnog projekta. Ovo može da bude poželjno ponašanje, jer vaš kod možda neće raditi sa najnovijim promenama subdmodula, te se tako sprečava neočekivano pucanje aplikacije.
U ovome članku ćemo koristiti dva projekta sa github-a: jedan kao glavni (https://github.com/choslee/gitSubmodulMasterParent i drugi kao subdmodul (https://github.com/choslee/gitSubmoduleChild).
Ubacivanje submodul-a u projekat
Dok smo u našem “parent” projektu za dodavnje submodula je potrebna samo njegova url adresa i korišćenje naredbe git submodule add:
1 |
gitSubmodulMasterParent>git submodule add https://github.com/choslee/gitSubmoduleChild |
Nakon izvšavanja ove naredbe pojavljuje se dva nova fila:
- .gitmodules
- Novi folder u kome se nalazi ceo podprojekat (našem primeru “gitSubmoduleChild”))
Zatim je ove izmene potrebno komitovari i poslati na cloud:
1 2 3 |
gitSubmodulMasterParent>git add . gitSubmodulMasterParent>git commit -m "adding submodule" gitSubmodulMasterParent>git push origin master |
Kloniranje projekta sa submodulom
Sada kad imamo projekat na cloud-u (npr. GitHub-u) koji u sebi sadrži subprojekat tj. submodul potrebno je da ga kloniramo. Pri kloniranju projekata sa submodulom postoji jedan korak više u odnosu na običan projekat. Prvo ćemo uraditi standardno kloniranje projekta:
1 |
git clone git@github.com:choslee/gitSubmodulMasterParent.git |
Nakon kloniranja se u okviru projekta vidi folder sa nazivom subprojekta, medjutim on je prazan! Da bi ga popunili potrebno je inicirati a zatim ga i ažurirati sa sledećim naredbama:
1 2 |
gitSubmodulMasterParent>git submodule init gitSubmodulMasterParent>git submodule update |
Nakon ove dve naredbe će se inicirati submodul a zatim i klonirati, ove dva naredbe možemo zameniti sa jednom:
1 |
gitSubmodulMasterParent>git submodule update --init |
Slanje izmena na cloud
Izmene na glavnom projektu
Ako napravimo izmene u okviru našeg glavnog projekta njih ćemo jednostavno poslati standardnim naredbama:
1 2 3 |
gitSubmodulMasterParent>git add . gitSubmodulMasterParent>git commit -m "neka poruka promene" gitSubmodulMasterParent>git push origin master |
Izmene na subprojektu
Medjutim ukoliko iz našeg projekta napravimo neke izmene na fajlovima submodula i proverimo status dobićemo sledeći izveštaj:
1 2 3 4 5 6 7 8 9 10 11 |
gitSubmodulMasterParent>git status On branch master Your branch is up to date with 'origin/master'. Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) (commit or discard the untracked or modified content in submodules) modified: gitSubmoduleChild (modified content) no changes added to commit (use "git add" and/or "git commit -a") |
U izveštaju vidimo da je glavni projekat nema izmena, ali vidimo da modifikovan sadržaj submodula. Ukoliko probamo da dodamo promene na index sa naredbom git add . ništa se neće dogoditi jer nema promena na glavnom projektu. Da bi poslali promene napravljene u submodulu potrebno je uraditi komit i push iz tog foldera, što znači da prvo moramo promeniti lokaciju:
1 |
gitSubmodulMasterParent>cd gitSubmoduleChild |
A zatim tu sve odraditi:
1 2 |
gitSubmoduleChild>git add . gitSubmoduleChild>git commit -m "poruka o promeni" |
Nakon ovoga će biti ažuriran repozitorijum koji je ubačen kao submodul.
NAPOMENA:
Uvek je potrebno prvo povući sve promene sa submodula pre pušovanja na server (pogledajte deo “Ažuriranje submodula”)
Trebamo napomenuti da se ove poslate promene neće videti na Github-u glavnog projekta, već na GitHub-u subprojekta.
Ažuriranje submodula
Kada želimo da ažuriramo podProjekat tj. submodul onda to ne možemo da uradimo samo ažuriranjem glavnog projekta sa standardnim naredbama:
1 |
gitSubmodulMasterParent>git pull origin master |
Jer standardnim pull-om neće biti ažuriran submodul, ni u lokalu ni na cloud-u. Na lokalu ćemo primetiti da nema novih ili izmenjenih fajlova dok na cloud-u (npr. GitHub-u) to uočavamo posmatrajući broj komita pored naziva foldera submodula. Taj broj komita mora da bude broj poslednjeg komita suprojekta. Pogledajte broj komita subprojekta na sledećoj slici:
Kao što se vidi na slici poslednje ažurirani komit ima broj “e14f576”, a kada pogledamo pravo stanje komita u subprojektu vidimo da ima jedan noviji komit “41b4c54” (pogledaj sliku dole):
I način
Potrebno je prvo ući u submodul:
1 |
cd gitSubmoduleChild |
Pa zatim povući njegove izmene:
1 |
gitSubmoduleChild>git pull origin master |
Kada se nakon ove naredbe vratimo u glavni projekni folder i proverimo status dobijamo sledeće:
1 2 3 4 5 6 7 8 9 10 11 |
gitSubmoduleChild>cd .. gitSubmodulMasterParent>git status On branch master Your branch is up to date with 'origin/master'. Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: gitSubmoduleChild (new commits) no changes added to commit (use "git add" and/or "git commit -a") |
Pa sada možemo da komitujemo i pošaljemo izmene na cloud:
1 2 3 |
gitSubmodulMasterParent>git add . gitSubmodulMasterParent>git commit -m "rucno azuriran submodul" gitSubmodulMasterParent>git push origin master |
Tek nakon ovoga će se na cloud-u prikazati poslednje izmene u okiviru submodula, a videće se i broj poslednjeg komita submodula “41b4c54”, vidi sliku:
II način
Ovaj način je lakši jer sve možemo da radimo dok smo u glavnom projektnom direktorijumu. Za ažuriranje submodula je potrebno koristi naredbu:
1 |
gitSubmodulMasterParent>git submodule update --remote |
Kada nakon ove naredbe proverimo status dobijamo sledeće:
1 2 3 4 5 6 7 8 9 10 |
gitSubmodulMasterParent>git status On branch master Your branch is up to date with 'origin/master'. Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: gitSubmoduleChild (new commits) no changes added to commit (use "git add" and/or "git commit -a") |
Ovde se vidi da promene postoje u okviri submodula, te je sada moguće komitovati i pušovati na claud:
1 2 3 |
gitSubmodulMasterParent>git add . gitSubmodulMasterParent>git commit -m "poruka da je azuriran submodul" gitSubmodulMasterParent>git push origin master |
Nakon čega će biti ažuriran broj pored submodula koji označava poslednji komit submodula.
Brisanje submodula iz projekta
Brisanje se vrši u par koraka:
- Obrišemo folder u našem projektu koji predstavlja submodul
- Ako imamo samo jedan submodul onda je dovoljno da obrišemo fajl “.gitmodules” u suprotnom je potrebno da ga editujemo i obrišemo deo vezan za naš submodul
- U okviru “.git” foldera nadjemo “modules” folder i u okviru njega obrišemo submodul.
- U okviru “.git” foldera potrebno naći fajl “config” i unutar njega obrisati deo vezan za naš submodul:
123[submodule "gitSubmoduleChild"]active = trueurl = https://github.com/choslee/gitSubmoduleChild
Nakon ovoga je neophodno ove izmene komitovati i pušovati na klaud.
NAPOMENA:
Brisanje submodula iz projkta ne utiče na sam repozitorijum tog submodula, on nastavlja da “živi” na cloud-u.