Submodule — loyiha ichida boshqa loyiha
Muammodan boshlaylik
Sizning uchta loyihangiz bitta umumiy dizayn tizimidan foydalanadi — SCSS o'zgaruvchilar, ikonlar, shriftlar — u alohida repozitoriyda: dokon/design-system. Uni har bir loyihaga qanday ulash kerak?
- Nusxalash — 43-darsdagi muammo: uchta turli versiya
- npm paket — ideal, lekin bu JS paket emas (fayllar to'plami), yoki loyiha npm ishlatmaydi
- Ichma-ich
git clone— 5-darsda ko'rdik: repo ichida repo — Git ichki repozitoriyni kuzatmaydi
Git ning o'rnatilgan yechimi — submodule: bir repozitoriy ichida boshqa repozitoriyga aniq commit bo'yicha havola.
Submodule nima?
dokon-web/ ← asosiy (superproject)
├── .git/
├── .gitmodules ← submodule lar ro'yxati
├── src/
└── vendor/design-system/ ← submodule — alohida repo
└── (dokon/design-system @ a3f9c2b)
Asosiy repozitoriy submodule ning fayllarini saqlamaydi — faqat ikki narsani:
- Qayerdan olish (URL) —
.gitmodulesda - Qaysi commit — asosiy repozitoriy tarixida
Submodule — aniq commit ga qotirilgan, branch ga emas. Dizayn tizimiga yangi commitlar qo'shilsa ham, siz ongli ravishda yangilamaguningizcha loyihangiz eski versiyada qoladi.
Submodule qo'shish
git submodule add git@github.com:dokon/design-system.git vendor/design-system
cat .gitmodules
[submodule "vendor/design-system"]
path = vendor/design-system
url = git@github.com:dokon/design-system.git
git status
Changes to be committed:
new file: .gitmodules
new file: vendor/design-system
git commit -m "build: design-system submodule qo'shildi"
git push
git diff --cached vendor/design-system ko'rsatadi — fayllar emas, faqat commit havolasi:
+Subproject commit a3f9c2b8e1d4f6a7b9c0d2e4f6a8b0c2d4e6f8a0
Submodule li loyihani clone qilish
[!WARNING] Oddiy
git clonesubmodule papkalarini bo'sh qoldiradi! Bu eng ko'p uchraydigan chalkashlik: "papka bor, lekin ichida hech narsa yo'q".
git clone --recurse-submodules git@github.com:dokon/dokon-web.git
Allaqachon oddiy clone qilgan bo'lsangiz:
git submodule update --init --recursive
--init—.gitmodulesdagi submodule larni ro'yxatdan o'tkazish--recursive— submodule ichidagi submodule lar uchun ham
Doim avtomatik bo'lishi uchun:
git config --global submodule.recurse true
Endi pull, switch kabi buyruqlar submodule larni ham yangilaydi.
Submodule ni yangilash
Dizayn tizimida yangi versiya chiqdi. Loyihangizda yangilash:
cd vendor/design-system
git fetch
git switch --detach v2.1.0 # yoki: git merge origin/main
cd ../..
git status
Changes not staged for commit:
modified: vendor/design-system (new commits)
git add vendor/design-system
git commit -m "build: design-system v2.1.0 ga yangilandi"
Yoki qisqaroq — barcha submodule larni o'z kuzatiladigan branch ining oxiriga:
git submodule update --remote
git add . && git commit -m "build: submodule lar yangilandi"
Hamkasb yangilaganidan keyin
Hamkasbingiz submodule ni yangi commit ga ko'chirdi. Siz git pull qildingiz — lekin submodule papkasi eski holatda:
git submodule update --recursive
(submodule.recurse true sozlangan bo'lsa — avtomatik.)
Submodule holati
git submodule status
a3f9c2b8e1d4... vendor/design-system (v2.1.0)
+e5f6a7b8c9d0... vendor/icons (heads/main)
-9f8e7d6c5b4a... vendor/fonts
| Belgi | Ma'nosi |
|---|---|
| (bo'shliq) | Asosiy repo kutgan commit da |
+ |
Boshqa commit da (yangilangan, lekin commit qilinmagan) |
- |
Initsializatsiya qilinmagan (bo'sh) |
U |
Merge conflict |
Submodule ichida ishlash
Submodule — to'liq Git repozitoriy. Ichiga kirib, o'zgartirib, commit va push qilish mumkin:
cd vendor/design-system
git switch main # detached HEAD dan chiqish!
# ... o'zgartirish ...
git commit -am "fix: tugma rangi"
git push
cd ../..
git add vendor/design-system
git commit -m "build: design-system tuzatishi"
git push
[!WARNING] Submodule standart holatda detached HEAD da (14-dars) — chunki u commit ga qotirilgan. Ichida commit qilishdan oldin
git switch mainqiling, aks holda commitlaringiz "yo'qolib" qolishi mumkin (reflog — 31-dars). Va avval submodule ni push qiling, keyin asosiy repo ni — aks holda hamkasblar mavjud bo'lmagan commit ga havola oladi.
Submodule ni o'chirish
git submodule deinit -f vendor/design-system
git rm -f vendor/design-system
rm -rf .git/modules/vendor/design-system
git commit -m "build: design-system submodule olib tashlandi"
Muqobillar
Submodule lar — kuchli, lekin noqulay: unutilgan --recurse-submodules, detached HEAD, push tartibi. Ko'p jamoalar muqobillarni afzal ko'radi:
| Vosita | Qachon |
|---|---|
| Paket menejeri (npm, Composer, pip) | Kod — kutubxona bo'lsa. Deyarli har doim eng yaxshi tanlov (43-dars) |
| Monorepo | Loyihalar birga o'zgaradi va bitta jamoaga tegishli (37-dars) |
| git subtree | Boshqa repo kodini to'g'ridan-to'g'ri nusxa sifatida, tarix bilan qo'shish — clone dan keyin qo'shimcha qadam kerak emas |
| Submodule | Tashqi repo ni aniq versiyada, alohida saqlash kerak va paket qilib bo'lmaydi (masalan, dotfiles, shablonlar, firmware, mavzular) |
Nima uchun shunday?
Nima uchun submodule branch ga emas, aniq commit ga qotiriladi — eng yangi versiyani avtomatik olish qulayroq emasmi?
Chunki "avtomatik eng yangi" — takrorlanmaydigan build degani. Bugun clone qilsangiz — bitta kod, ertaga — boshqa, va hech narsani o'zgartirmagan bo'lsangiz ham loyiha buzilishi mumkin. Commit ga qotirish asosiy repozitoriyning har bir commit i aynan qaysi submodule versiyasi bilan ishlashini aniq belgilaydi: bir yil oldingi commit ni olsangiz — submodule ham bir yil oldingi holatda. Bu package-lock.json (35-dars) bilan bir xil g'oya: bog'liqliklarni qotirish va yangilashni ongli harakat qilish — commit bilan, review bilan, kerak bo'lsa revert bilan.
Xulosa
Eslab qoling:
- Submodule — repozitoriy ichida boshqa repozitoriyga aniq commit bo'yicha havola
git submodule add URL papka→.gitmodules+ commit- Clone:
--recurse-submodulesyokigit submodule update --init --recursive submodule.recurse true— avtomatik yangilanish- Yangilash: ichida
fetch+switch, yokiupdate --remote→ asosiy repo daadd+commit - Ichida ishlash: avval
git switch main; avval submodule ni push qiling git submodule status—+yangilangan,-bo'sh- Ko'p hollarda yaxshiroq: paket menejeri yoki monorepo
Keyingi dars
46-dars: git worktree — bir vaqtda bir nechta branch bilan ishlash