Submodule — loyiha ichida boshqa loyiha

~15 daq · Git · Ilg'or Git

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:

  1. Qayerdan olish (URL) — .gitmodules da
  2. 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 clone submodule 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 — .gitmodules dagi 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 main qiling, 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-submodules yoki git submodule update --init --recursive
  • submodule.recurse true — avtomatik yangilanish
  • Yangilash: ichida fetch + switch, yoki update --remote → asosiy repo da add + 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