Submodule adalah repository Git yang hidup di dalam repository lain pada jalur tertentu, dan commit induknya menyimpan titik versi yang tepat dari repository anak itu. Topik ini memperkenalkan cara pemasangannya, cara clone yang menangkapnya, dan alasan fitur ini dikenal menyulitkan. Pemahaman batasnya sama pentingnya dengan cara memakainya, karena submodule sering dipilih padahal tidak dibutuhkan.
Repository di dalam repository#
Kebutuhan di balik submodule adalah menyertakan proyek lain tanpa menyalin riwayatnya, misalnya pustaka bersama yang dipakai beberapa aplikasi. Submodule menjawabnya dengan dua lapisan: repository anak tetap repository Git yang utuh dengan riwayat dan remote-nya sendiri, sedangkan repository induk menyimpan tiga hal saja, yaitu berkas .gitmodules yang menyebut asal dan jalurnya, entri pada pohon proyek, dan hash commit anak yang dipakai pada saat itu.
Lapisan kedua itulah yang khas: repository induk tidak mengikuti perkembangan pustaka secara otomatis, melainkan mengunci satu titik versi yang di-commit secara sadar. Peningkatan versi pustaka adalah commit pada repository induk yang mengubah hash tersebut, sehingga setiap anggota tim dan setiap mesin membangun dengan pustaka yang persis sama.
Memasang submodule#
Siapkan pustaka dan proyek induknya, lalu tambahkan pustaka sebagai submodule.
# tanggal commit ditetapkan agar keluaran contoh dapat direproduksi secara persis
export GIT_AUTHOR_DATE="2026-11-01T09:00:00+07:00"
export GIT_COMMITTER_DATE="2026-11-01T09:00:00+07:00"rm -rf /tmp/lab-lib /tmp/lab-sub /tmp/lab-sub-salinan /tmp/lab-sub-r
git init -b main /tmp/lab-lib
cd /tmp/lab-lib
git config user.name "Dewi"
git config user.email "[email protected]"
printf "def sapa():\n return 'Halo'\n" > lib.py
git add lib.py
git commit -m "Fungsi sapa"
cd /tmp
git init -b main /tmp/lab-sub
cd /tmp/lab-sub
git config user.name "Budi"
git config user.email "[email protected]"
printf "# Proyek Aplikasi\n" > README.md
git add README.md
git commit -m "Awal proyek"
git -c protocol.file.allow=always submodule add /tmp/lab-lib lib
git commit -m "Tambah pustaka sebagai submodule"
cat .gitmodulesInitialized empty Git repository in /tmp/lab-lib/.git/
[main (root-commit) 302edb1] Fungsi sapa
1 file changed, 2 insertions(+)
create mode 100644 lib.py
Initialized empty Git repository in /tmp/lab-sub/.git/
[main (root-commit) a00ec7d] Awal proyek
1 file changed, 1 insertion(+)
create mode 100644 README.md
Cloning into '/tmp/lab-sub/lib'...
done.
[main 7b1842c] Tambah pustaka sebagai submodule
2 files changed, 4 insertions(+)
create mode 100644 .gitmodules
create mode 160000 lib
[submodule "lib"]
path = lib
url = /tmp/lab-libBerkas .gitmodules menyimpan asal dan jalurnya, dan tipe 160000 pada berkas lib adalah penanda khusus Git untuk entri submodule. Perhatikan opsi protocol.file.allow=always pada perintahnya: sejak Git 2.38.1, protokol lokal berkas dinonaktifkan secara bawaan pada operasi submodule demi keamanan, sehingga contoh lokal ini menyalakannya secara eksplisit. Pada remote berbentuk URL HTTPS, opsi itu tidak diperlukan.
Clone yang menangkap submodule#
Clone biasa tidak mengisi isi submodule, dan inilah kejutan yang paling sering ditemui pemula.
cd /tmp
git clone -q lab-sub lab-sub-salinan
ls lab-sub-salinan/lib
git -c protocol.file.allow=always clone -q --recurse-submodules lab-sub lab-sub-r
ls lab-sub-r/liblib.pyFolder lib pada salinan pertama kosong, dan ls tidak menampilkan apa pun, karena clone hanya mencatat titik versi yang dikunci tanpa mengunduh isinya. Perintah pelengkapnya adalah git submodule update --init --recursive pada salinan yang sudah ada, sedangkan clone dengan opsi --recurse-submodules menyelesaikannya sekali jalan, dan lib.py muncul pada salinan kedua.
Pembaruan pustaka mengikuti dua langkah yang berurutan, yaitu memperbarui repository anak pada foldernya sampai titik versi yang diinginkan, lalu commit perubahan hash pada repository induk. Lupa langkah kedua adalah kesalahan yang paling umum, karena status induknya terus menyatakan ada perubahan pada submodule yang belum di-commit.
Mengapa submodule menyulitkan#
Biaya submodule terletak pada keadaan ganda yang harus dipelihara. Ada dua riwayat, dua HEAD, dan dua aturan sinkronisasi pada satu folder proyek, sehingga kesalahan kecil seperti lupa --init atau lupa commit hash baru langsung berdampak pada teman tim yang meng-clone. Selain itu, status submodule ditampilkan pada banyak alat sebagai berkas berubah, dan mesin integrasi berkelanjutan perlu disetel khusus untuk mengisinya.
Karena itu, aturan penentuannya sederhana: submodule tepat untuk pustaka eksternal yang memiliki riwayat dan siklus rilis sendiri, dan kurang tepat untuk kode yang dikembangkan bersamaan pada tim yang sama. Untuk kasus kedua, satu repository dengan struktur folder biasa hampir selalu lebih mudah, dan pertimbangan itu dibahas lebih jauh pada perbandingan monorepo dan polyrepo.
Ringkasan#
- Submodule menyertakan repository lain pada satu jalur, dengan repository induk mengunci satu hash commit anaknya.
- Berkas
.gitmodulesmenyimpan asal dan jalur submodule, dan peningkatan versinya adalah commit pada repository induk. - Clone biasa membiarkan submodule kosong, dan isinya diambil melalui
--recurse-submodulesataugit submodule update --init. - Keadaan ganda yang harus dipelihara menjadikan submodule tepat untuk pustaka eksternal, bukan untuk kode yang tumbuh bersama.
Referensi#
- git-submodule — Git Documentation — rujukan seluruh subperintah submodule.
- Git Tools - Submodules — Pro Git — bab Pro Git tentang submodule.