Asosiy kontentga o‘tish

Maqolalar 9 daqiqa 79 ko‘rish

Git submodullar: repozitoriy ichida repozitoriy

Submodule bir repozitoriyga boshqasining muayyan commitini ulaydi: gitlink, .gitmodules, faol submodulelar, tashqi kutubxona bilan ishlash tartibi, merge konflikti va submodule'ni olib tashlash.

git devops

Mundarija

Loyihangiz boshqa repozitoriyga tayansa, uni ko‘chirib qo‘yishning o‘rniga submodule sifatida ulash mumkin. Bu bo‘lim submodule qanday saqlanishini (gitlink va .gitmodules) va kundalik ishda nima qilish kerakligini ko‘rsatadi. Submodule chalkash mavzu, shuning uchun ishlatishdan oldin o‘qib chiqing.

Bu ma’lumotnoma, dars emas

Bu qism Git'ning rasmiy qo‘llanmasi (git help submodules, Git 2.50.1) asosida o‘zbekchaga o‘girilgan. Ketma-ket bajariladigan dars emas: kerak bo‘lganda ochib, kerakli joyini o‘qiysiz. Git'ni noldan o‘rganmoqchi bo‘lsangiz, avval Git va GitHub darslarini bajaring.

Nomi#

gitsubmodules — bir repozitoriyni boshqasining ichiga ulash.

Tavsif#

Submodule bir Git repozitoriysiga boshqa Git repozitoriysining muayyan commitini joylashtirish imkonini beradi. Tashqi (superproject) repozitoriy submodule fayllarini bevosita saqlamaydi; uning tree’sida 160000 rejimli gitlink yozuvi orqali submodule commit ID’sini saqlaydi.

Odatda yana .gitmodules fayli saqlanadi. U submodule nomi, yo‘li va tavsiya etilgan URL’ni beradi:

INI
[submodule "libfoo"]
    path = deps/libfoo
    url = https://example.com/libfoo.git

Submodule qo‘shish:

Terminal
git submodule add https://example.com/libfoo.git deps/libfoo
git commit -m "Add libfoo submodule"

Superproject aynan submodule’dagi joriy commitni qayd etadi. Submodule branchining nomi yoki “eng yangi versiya” avtomatik saqlanmaydi.

Submodule sozlamalari#

Submodule xatti-harakatini bir nechta joy boshqaradi. Ularning ustuvorligi vaziyatga qarab farq qiladi.

.gitmodules#

Repozitoriy bilan birga commit qilinadigan tavsiya etilgan sozlama:

INI
[submodule "libfoo"]
    path = deps/libfoo
    url = ../libfoo.git
    branch = main
    update = checkout

Muhim kalitlar:

  • submodule.<name>.path — superproject ichidagi yo‘l;
  • submodule.<name>.url — klonlash manzili;
  • submodule.<name>.branch — remote’dan yangilashda kuzatiladigan branch;
  • submodule.<name>.update — checkout, merge, rebase, none yoki maxsus buyruq;
  • submodule.<name>.ignore — status/diff qaysi o‘zgarishlarni e’tiborsiz qoldirishi;
  • submodule.<name>.fetchRecurseSubmodules — fetch ichkariga rekursiya qilishi;
  • submodule.<name>.shallow — shallow clone tavsiyasi.

.gitmodules ishonchsiz repozitoriydan kelishi mumkin. Xavfsizlik sababli ayrim qiymatlar, masalan custom update = !command, undan bevosita bajarilmaydi.

.git/config#

Mahalliy, foydalanuvchiga xos sozlama. git submodule init .gitmodules dagi mos qiymatlarni shu yerga ko‘chiradi:

Terminal
git submodule init
git config submodule.libfoo.url ssh://git@example.com/libfoo.git

Mahalliy URL .gitmodules ni o‘zgartirmasdan override qilinadi.

Buyruq satri#

Ko‘p buyruqlarda --recurse-submodules, --remote, --checkout, --merge, --rebase, --depth kabi parametrlar bir martalik xatti-harakatni tanlaydi.

Superproject commitidagi asosiy manba — qaysi submodule commit checkout qilinishi kerakligini bildiruvchi gitlink:

Terminal
git ls-tree HEAD deps/libfoo
160000 commit <object-id>    deps/libfoo

Submodule holatlari#

Submodule quyidagi shakllarda bo‘lishi mumkin:

Deinitialized#

Gitlink va .gitmodules yozuvi mavjud, ammo ishchi katalog checkout qilinmagan va mahalliy submodule.<name>.url yo‘q.

Terminal
git submodule deinit deps/libfoo

Initialized, ammo checkout qilinmagan#

Mahalliy konfiguratsiya bor, lekin ishchi daraxt hali yaratilmagan.

Terminal
git submodule init deps/libfoo

Populated#

Submodule repozitoriysi va ishchi daraxti mavjud, gitlink ko‘rsatgan commit checkout qilingan:

Terminal
git submodule update --init deps/libfoo

Modified#

Submodule ichida commit qilinmagan o‘zgarish bor yoki uning HEAD commit’i superproject qayd etgan gitlink’dan farq qiladi:

Terminal
git status
git diff --submodule
git submodule status

git submodule status prefikslari:

  • bo‘sh joy — kutilgan commit checkout qilingan;
  • - — initialize qilinmagan;
  • + — boshqa commit checkout qilingan;
  • U — merge konflikti bor.

Old-form submodule#

Eski Git versiyalarida submodule .git katalogi bevosita submodule ishchi katalogi ichida bo‘lgan. Zamonaviy Git odatda Git katalogini superproject .git/modules/<name>/ ostida saqlab, submodule ichida gitfile qoldiradi.

Terminal
git submodule absorbgitdirs

Bu eski ichki .git kataloglarini zamonaviy joylashuvga ko‘chiradi.

Deleted submodule#

Gitlink va .gitmodules yozuvi tarixdan o‘chirilgan bo‘lsa ham, lokal Git katalogi xavfsizlik uchun .git/modules/ da qolishi mumkin. Uni qo‘lda o‘chirish qayta tiklab bo‘lmaydigan local commitlarni yo‘qotishi mumkin; avval ref va obyektlarni tekshiring.

Faol submodulelar#

Git ayrim rekursiv amallarni faqat active submodulelarda bajaradi. Faollik quyidagi qoidalardan aniqlanadi:

  1. submodule.active pathspec’iga mos kelsa — faol.
  2. submodule.<name>.active true bo‘lsa — faol, false bo‘lsa — faol emas.
  3. Yuqoridagilar belgilanmagan va submodule.<name>.url mavjud bo‘lsa — tarixiy moslik uchun faol.

Misol:

INI
[submodule]
    active = deps/*
[submodule "large-data"]
    active = false

Faqat kerakli submodulelarni initialize qilish katta loyihalarda klonlash va fetch vaqtini kamaytiradi.

Terminal
git submodule update --init deps/libfoo
git submodule update --init --recursive

Tashqi kutubxona bilan ishlash#

Submodule tashqi kutubxonaning aniq, tekshirilgan versiyasini loyiha bilan bog‘lash uchun ishlatilishi mumkin.

Loyiha foydalanuvchisi#

Submodulelar bilan klonlash:

Terminal
git clone --recurse-submodules <superproject-url>

Oddiy klon allaqachon qilingan bo‘lsa:

Terminal
git submodule update --init --recursive

Superproject yangilangach gitlinkdagi versiyalarni chiqarish:

Terminal
git pull
git submodule update --init --recursive

Rekursiv pull:

Terminal
git pull --recurse-submodules

Bu yangi commitlarni fetch qiladi, ammo checkout strategiyasi va mahalliy o‘zgarishlarga qarab alohida submodule update talab qilinishi mumkin.

Kutubxona versiyasini yangilovchi dasturchi#

Submodule ichida kerakli commitga o‘ting:

Terminal
cd deps/libfoo
git fetch origin
git switch --detach <tested-commit>
cd ../..
git add deps/libfoo
git commit -m "Update libfoo to <version>"

Superproject commit’i gitlink yangilanishini saqlaydi. Hamkasblar aynan shu commitni checkout qiladi.

Remote branchning so‘nggi holatiga yangilash:

Terminal
git submodule update --remote deps/libfoo
git diff --submodule
git add deps/libfoo
git commit

--remote avtomatik olingan natijani sinovsiz commit qilish degani emas; dependency API, lockfile, litsenziya va testlarni tekshiring.

Submodule ichida o‘zgarish qilish#

Submodule odatda detached HEAD’da bo‘ladi. Ishni yo‘qotmaslik uchun avval branch yarating:

Terminal
git -C deps/libfoo switch -c my-fix
# tahrir, test
git -C deps/libfoo add .
git -C deps/libfoo commit
git -C deps/libfoo push origin my-fix
git add deps/libfoo
git commit -m "Use libfoo fix"

Avval submodule commit’ini unga tegishli remote’ga push qiling, keyin superproject gitlink’ini push qiling. Aks holda hamkasblar superproject ko‘rsatgan obyektni ola olmaydi.

Push vaqtida tekshirish:

Terminal
git push --recurse-submodules=check
# yoki submodule commitlarini ham yuborish:
git push --recurse-submodules=on-demand

Sun’iy ajratilgan repozitoriy#

Katta loyiha tashkiliy yoki access-control sabablari bilan bir necha repozitoriyga bo‘linib, superproject orqali birlashtirilishi mumkin. Bunda submodulelar bir-biriga mustaqil bo‘lmasligi ehtimoli bor.

Tavsiya etiladigan sozlamalar:

Terminal
git config status.submoduleSummary true
git config diff.submodule log
git config fetch.recurseSubmodules on-demand
git config push.recurseSubmodules check

Branchlarni birga yuritish kerak bo‘lsa:

Terminal
git submodule foreach --recursive 'git status --short'
git submodule foreach --recursive 'git fetch origin'

foreach ichidagi shell kodiga ehtiyot bo‘ling; submodule nomi va yo‘li ishonchsiz bo‘lishi mumkin.

Superproject branchini almashtirishda:

Terminal
git switch feature
git submodule update --init --recursive

Submoduledagi mahalliy o‘zgarish checkout’ga xalaqit bersa, Git ularni jim o‘chirib yubormasligi kerak. O‘zgarishlarni commit yoki stash qiling, keyin qayta urinib ko‘ring.

Parallel yangilash:

Terminal
git submodule update --init --recursive --jobs 8

Ichki tuzilish#

Git katalogi#

Zamonaviy joylashuv:

Fayl tuzilishi
superproject/.git/modules/<name>/
superproject/<path>/.git   # gitdir: ../../.git/modules/<name> ko‘rsatkichli fayl

Bu submodule ishchi katalogi o‘chirilganda ham uning local obyektlari va branchlarini saqlab qolishga yordam beradi.

Tree yozuvi:

Misol
160000 commit <submodule-commit-id> <path>

Superproject obyektlar bazasi submodule commit obyektini majburan saqlamaydi. Uni submodule remote’dan olish kerak.

.gitmodules xavfsizligi#

.gitmodules versiya nazoratida va remote’dan keladi. Git protokolga mos kelmaydigan yoki xavfli URL/command’larni cheklaydi. Klonlangan loyiha kodini, hooklarini yoki submodule ichidagi build skriptlarini ishonch hosil qilmasdan ishga tushirmang.

URL o‘zgarganda mahalliy konfiguratsiyani sinxronlash:

Terminal
git submodule sync --recursive
git submodule update --init --recursive

Submodule merge konflikti#

Ikki branch gitlinkni turli commitga yangilasa, Git faqat bir tomon ikkinchisining ajdodi bo‘lganda avtomatik tanlay oladi. Aks holda submodulega kirib, mos commitni checkout yoki merge qiling:

Terminal
git -C deps/libfoo log --graph --all --oneline
git -C deps/libfoo switch -c resolve <one-side>
git -C deps/libfoo merge <other-side>
git add deps/libfoo
git commit

Hosil qilingan submodule merge commit’ini remote’ga push qilishni unutmang.

Submodule olib tashlash#

Gitlink va .gitmodules yozuvini versiya nazoratidan olib tashlash:

Terminal
git rm deps/libfoo
git commit -m "Remove libfoo submodule"

.git/modules/libfoo dagi lokal repozitoriyni darhol o‘chirish majburiy emas. Unda push qilinmagan commit bo‘lishi mumkin; butunlay tozalashdan oldin tekshiring.

Shuningdek qarang#

git-submodule(1), gitmodules(5), git-config(1), git-diff(1).

Git to‘plami#

git(1) buyruqlar to‘plamining bir qismi.

9 daqiqa 79 marta o‘qildi