Git submodule: jinsi ya kuongeza, kusasisha na kuondoa moduli ndogo
Git submodule ni repo nyingine iliyowekwa ndani ya folda ya mradi wako na kufungwa kwenye commit fulani. Inaongezwa kwa git submodule add <url> <njia>, inapatikana wakati wa clone kwa git clone --recurse-submodules, inasasishwa kwa git submodule update --remote, na kuondolewa kwa git submodule deinit na git rm.
Git submodule (moduli ndogo) ni repo tofauti ya Git iliyowekwa ndani ya folda ya mradi wako. Sifa yake kuu: repo kuu haihifadhi faili za moduli ndogo, bali inahifadhi kiungo kwa commit fulani ndani yake. Kwa hiyo kila anayeclone mradi atapata moduli ndogo katika toleo lilelile, hadi wewe mwenyewe ubadilishe kwa makusudi.
Moduli ndogo hutumika unapotaka kuunganisha maktaba ya mtu mwingine bila meneja wa vifurushi, kushiriki msimbo wa pamoja kati ya miradi kadhaa, au kuweka mandhari au firmware kwenye repo yake yenye historia yake.
Jinsi git submodules zinavyofanya kazi
Moduli ndogo ina sehemu tatu, na kuelewa uhusiano wake kunaondoa tatizo nyingi:
- Faili
.gitmoduleskwenye mzizi wa mradi — inacommitiwa na kueleza ni njia ipi inatoka kwenye URL ipi. - Ingizo la gitlink kwenye mti wa commit — kipengele maalum chenye hali
160000, ambapo badala ya maudhui kuna hash ya commit ya moduli ndogo. - Repo yenyewe ya moduli ndogo — data yake inahifadhiwa kwenye
.git/modules/<jina>ya repo kuu, na kwenye folda ya moduli kuna faili.gitinayoelekeza huko.
cat .gitmodules
[submodule "libs/ui-kit"]
path = libs/ui-kit
url = https://github.com/example/ui-kit.git
git ls-tree HEAD libs/
160000 commit 8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c libs/ui-kit
Angalia: repo kuu inarekodi commit hasa, si tawi. Hii ndiyo tofauti ya msingi kati ya submodule ya Git na utegemezi wa "toleo la mwisho kutoka main".
Jinsi ya kuongeza moduli ndogo
git submodule add https://github.com/example/ui-kit.git libs/ui-kit
Cloning into '/home/dev/shop/libs/ui-kit'...
done.
git status
new file: .gitmodules
new file: libs/ui-kit
git commit -m "Ongeza ui-kit kama moduli ndogo"
Amri hii inaclone repo, kuunda au kuongeza .gitmodules, na kuongeza gitlink kwenye index. Kilichobaki ni kucommit. Ukiacha njia, folda itapewa jina la repo.
Ili moduli ifuate tawi fulani wakati wa kusasisha, litaje tangu mwanzo: git submodule add -b develop <url> <njia>. Tawi litaandikwa kwenye .gitmodules kama branch = develop.
URL ya jamaa
Ikiwa moduli iko kwenye seva ileile, unaweza kutumia njia ya jamaa: git submodule add ../ui-kit.git libs/ui-kit. Inatatuliwa kulingana na URL ya repo kuu, kwa hiyo inafanya kazi kwa SSH na HTTPS, kulingana na jinsi mradi ulivyoclone.
Jinsi ya kuclone mradi wenye moduli ndogo
Malalamiko ya kawaida: "nimeclone, lakini folda ya moduli ni tupu". Kwa chaguo-msingi git clone haipakui moduli ndogo. Njia sahihi ni:
git clone --recurse-submodules https://github.com/example/shop.git
Ikiwa mradi tayari umeclone bila moduli ndogo:
git submodule update --init --recursive
--init husajili moduli kutoka .gitmodules kwenye .git/config yako ya ndani, update inazipakua na kubadili kwenye commit iliyofungwa, na --recursive inafanya vivyo hivyo kwa moduli ndani ya moduli.
Jinsi ya kusasisha moduli ndogo
Hapa ni muhimu kutofautisha kazi mbili: "pata toleo ambalo wenzangu wamecommit" na "hamia toleo jipya la maktaba".
Pata toleo lililofungwa kwenye mradi
Baada ya git pull gitlink kwenye repo kuu inaweza kubadilika, lakini faili za moduli hazijisasishi zenyewe — git status itaonyesha modified: libs/ui-kit (new commits). Sawazisha:
git pull
git submodule update --init --recursive
Ili usifanye hili kwa mkono, washa otomatiki: git config submodule.recurse true. Kisha pull, checkout na switch zitasasisha moduli zenyewe. Mbadala kwa wito mmoja ni git pull --recurse-submodules.
Hamia toleo jipya la maktaba
# Chaguo 1: vuta commit ya mwisho ya tawi lililofuatiliwa
git submodule update --remote libs/ui-kit
# Chaguo 2: chagua toleo kwa mkono
cd libs/ui-kit
git fetch
git checkout v3.2.0
cd ../..
# Kwa njia zote mbili — funga toleo jipya kwenye repo kuu
git add libs/ui-kit
git commit -m "Sasisha ui-kit hadi v3.2.0"
--remote inachukua tawi kutoka kwenye parameta branch ya .gitmodules, na ikiwa haipo — tawi ambalo HEAD ya repo ya moduli inaelekeza (kwa kawaida main). Bila commit kwenye repo kuu, wenzako hawatapata toleo jipya: kusasisha moduli ni mabadiliko ya gitlink ambayo lazima icommitiwe.
Kuona kilichobadilika kwenye moduli ni rahisi hivi:
git diff --submodule=log
git config diff.submodule log # fanya muundo huu kuwa chaguo-msingi
git submodule status
8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c libs/ui-kit (v3.1.0)
+1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b libs/charts (v1.4.0-3-g1a2b3c4)
Kiambishi katika git submodule status: - — moduli haijaanzishwa, + — commit yake ya sasa ni tofauti na ile iliyofungwa kwenye repo kuu, U — mgongano wa muunganiko.
Jinsi ya kubadilisha moduli ndogo
Baada ya git submodule update, moduli iko kwenye hali ya detached HEAD — kwenye commit maalum, si tawi. Ukianza kucommit hivyo, commit zinaweza kupotea kwenye update ijayo. Mpangilio sahihi wa kazi:
cd libs/ui-kit
git switch main # simama kwenye tawi
# ... marekebisho ...
git commit -am "Rekebisha nafasi ya kitufe"
git push # kwanza sukuma moduli!
cd ../..
git add libs/ui-kit
git commit -m "ui-kit: nafasi ya kitufe imerekebishwa"
git push
Mpangilio wa push ni muhimu. Ukisukuma repo kuu kabla ya moduli, seva itaelekeza kwenye commit ambayo hakuna mtu mwingine anayeweza kuipakua, na kwa wenzako git submodule update itaanguka na fatal: remote error: upload-pack: not our ref au did not contain. Kinga husaidiwa na git push --recurse-submodules=check (itakataa push ikiwa moduli haijasukumwa) au =on-demand (itasukuma moduli kwanza yenyewe).
Jinsi ya kuondoa moduli ndogo
Zamani kuondoa kulihitaji kuhariri faili kadhaa kwa mkono. Kwenye matoleo ya kisasa ya Git hatua tatu zinatosha:
git submodule deinit -f libs/ui-kit # ondoa kwenye .git/config na safisha folda
git rm -f libs/ui-kit # ondoa gitlink na ingizo la .gitmodules
rm -rf .git/modules/libs/ui-kit # futa data iliyohifadhiwa ya moduli
git commit -m "Ondoa moduli ndogo ui-kit"
Hatua ya mwisho si lazima kwa usahihi, lakini bila hiyo, ukiongeza tena moduli kwenye njia ileile, Git inaweza kulalamika kwamba folda ya ndani tayari ipo (A git directory for 'libs/ui-kit' is found locally).
Ikiwa URL ya moduli imebadilika
Repo imehamia — rekebisha .gitmodules na usawazishe usanidi wa ndani:
git submodule set-url libs/ui-kit https://gitlab.com/example/ui-kit.git
git submodule sync --recursive
git commit -am "Anwani mpya ya ui-kit"
Wenzako pia wanapaswa kutekeleza git submodule sync baada ya pull: URL kutoka .gitmodules inakiliwa kwenye .git/config yao tu wakati wa init au sync.
Amri muhimu kwa moduli nyingi
| Kazi | Amri |
|---|---|
| Orodha na hali | git submodule status --recursive |
| Endesha amri kwenye kila moja | git submodule foreach 'git switch main && git pull' |
| Kuharakisha upakuaji | git submodule update --init --jobs 4 |
| Pakua bila historia | git submodule update --init --depth 1 |
| Muhtasari mfupi kwenye status | git config status.submoduleSummary true |
Matatizo ya kawaida na moduli ndogo
- Folda tupu baada ya clone — init haijafanyika. Suluhisho:
git submodule update --init --recursive. - "modified: (new commits)" mara baada ya pull — repo kuu inaelekeza kwenye commit nyingine, lakini faili ni za zamani. Suluhisho:
git submodule update. - Moduli ilirudishwa nyuma kwa bahati mbaya — ulitekeleza
git add .wakati moduli ilikuwa kwenye commit ya zamani, ukacommit kurudi nyuma kwa toleo. Daima angaliagit diff --submodulekabla ya kucommit. - Mgongano wa gitlink wakati wa kuunganisha — matawi mawili yalisasisha moduli hadi commit tofauti. Ingia kwenye moduli, chagua commit inayohitajika (mara nyingi mpya zaidi inayojumuisha mabadiliko yote mawili), kisha
git add njiana umalize merge. - Moduli ya faragha kwenye CI — jenzi haiwezi kupakua moduli bila ruhusa. Mpe CI ufunguo au tokeni ya repo ya moduli; URL za jamaa hurahisisha usanidi.
Moduli ndogo kwenye timu: makubaliano
Matatizo mengi hayatokani na Git yenyewe, bali na washiriki kufanya mambo kwa njia tofauti. Sheria chache za kuweka kwenye README ya mradi:
- Clone kwa
--recurse-submodulespekee, na washasubmodule.recurse truekwa kila mtu. - Sasisha moduli kwa commit tofauti yenye ujumbe wazi: toleo gani na kwa nini.
- Usirekebishe msimbo wa moduli ndani ya mradi mkuu bila commit tofauti na push kwenye moduli yenyewe.
- Kwenye CI, tekeleza wazi
git submodule update --init --recursivena uthibitishe kwamba jenzi haitegemei mabadiliko ya ndani.
Ili kuthibitisha kwenye CI kwamba commit zote zilizofungwa za moduli zinapatikana, clone safi inatosha: ikiwa mtu alisahau kusukuma moduli, jenzi itaanguka kwenye hatua ya update, si kwa mwenzako wiki moja baadaye.
git clone --recurse-submodules --jobs 4 "$REPO_URL" build
cd build
git submodule status --recursive
Moduli ndogo au njia mbadala
Moduli ndogo zinatoa udhibiti sahihi wa toleo na historia tofauti, lakini zinaongeza hatua za mkono kwa kila mshiriki. Ikiwa msimbo ni maktaba ya kawaida, meneja wa vifurushi (npm, pip, Composer, Go modules) ni rahisi zaidi. Ikiwa unataka msimbo wa mtu mwingine ukae ndani ya mradi na kuclone bila amri za ziada, angalia git subtree: inanakili historia kwenye repo kuu, na wenzako hawahitaji kujua chochote. Kwa huduma nyingi zinazohusiana, timu mara nyingi huchagua monorepo. Moduli ndogo inafaa wakati msimbo uliomo una maisha yake, matoleo yake na timu yake.
Hitimisho
Git submodule ni kiungo kwa commit maalum ya repo nyingine. Kuongeza ni git submodule add, kupata ni --recurse-submodules au update --init, kusasisha hadi toleo jipya ni update --remote pamoja na commit kwenye repo kuu, na kuondoa ni deinit, git rm na kusafisha .git/modules. Kumbuka detached HEAD ndani ya moduli na mpangilio wa push. Zana za hali ya juu za Git zinafundishwa kwa vitendo katika kozi ya Git.
Maswali ya mara kwa mara
Kwa nini moduli ndogo iko kila mara kwenye detached HEAD?
Repo kuu inahifadhi hash ya commit, si tawi, na git submodule update inabadilisha moduli kwenye commit hiyo. Kwa kubadilisha, hamia kwenye tawi kwa mkono au tumia git submodule update --remote --merge.
Je, inawezekana kufunga moduli ndogo kwenye tag?
Moja kwa moja hapana, lakini unaweza kuhamia tag ndani ya moduli kwa git checkout na kucommit kwenye repo kuu commit inayotokana; tag itaonekana kwenye mabano ya git submodule status.
Je, GitHub inapakua moduli ndogo kwenye faili ya ZIP?
Hapana, kumbukumbu za msimbo za GitHub hazijumuishi yaliyomo ya moduli ndogo, folda zitakuwa tupu. Tumia git clone --recurse-submodules.
git submodule inatofautianaje na git subtree?
Submodule huhifadhi kiungo kwa commit ya repo ya nje na inahitaji amri tofauti kupata msimbo, wakati subtree hunakili faili na historia moja kwa moja kwenye repo kuu.
Je, inawezekana kuhamisha moduli ndogo kwenye folda nyingine?
Ndiyo, kwa amri ya git mv njia-ya-zamani njia-mpya: Git itasasisha .gitmodules na viungo vya ndani yenyewe, kilichobaki ni kucommit.
Mada hii inafundishwa kwa kina pamoja na mazoezi katika kozi “Git kutoka mwanzo hadi msanidi programu anayejiweza”.
Nenda kwenye kozi