Monorepo menggabungkan banyak layanan dalam satu repository agar bisa direfaktor serentak, tetapi harganya dibayar oleh semua orang: insinyur yang hanya menyentuh service-a tetap meng-clone service-b, direktori docs, dan ratusan megabyte aset yang tak pernah dibuka. Sparse checkout memotong biaya itu dari sisi working directory — Git tetap memegang repository utuh, tetapi hanya mengeluarkan direktori pilihan ke disk. Kita akan membuktikannya pada monorepo mini, membongkar pola yang Git bangun di balik layar, lalu membedakan teknik ini dari partial clone yang sering tertukar dengannya.
Monorepo Mini dan Mode Cone #
Repository latihan menampung dua layanan plus dokumentasi, dengan satu commit tambahan di service-b agar riwayatnya tidak sepele:
mkdir latihan-monorepo && cd latihan-monorepo
git init -b main
git config user.name "Budi Santoso"
git config user.email "[email protected]"
mkdir service-a service-b docs
printf 'api layanan a\n' > service-a/main.go
printf 'tes layanan a\n' > service-a/main_test.go
printf 'api layanan b\n' > service-b/main.go
printf 'panduan monorepo\n' > docs/panduan.md
printf 'Monorepo Toko Berkah\n' > README.md
git add -A
git commit -m "Struktur awal monorepo"
printf 'router layanan b\n' > service-b/router.go
git add service-b/router.go
git commit -m "Tambah router layanan B"Dari luar, repository di-clone seperti biasa, lalu mode sparse diaktifkan:
cd ..
git clone latihan-monorepo klon-monorepo
cd klon-monorepo
git sparse-checkout init --cone
lsOutput yang Dihasilkan:
README.mdSatu baris itu adalah momen pentingnya: service-a, service-b, dan docs lenyap dari disk. Git versi 2.47 (versi yang dipakai buku ini) memakai mode cone sebagai mode bawaan; flag --cone hanya menegaskan pilihan itu. Nama “cone” menggambarkan bentuk cakupannya: berkas di root selalu diambil, lalu direktori level atas masuk hanya bila dipilih bersama seluruh isinya — seperti kerucut yang tumbuh dari root. Mode ini cepat karena Git cukup membandingkan awalan path, tanpa membaca isi berkas.
Memilih Direktori dengan set #
Perintah set menuliskan pilihan direktori sekaligus mengeluarkannya ke working directory:
git sparse-checkout set service-a docs
lsOutput yang Dihasilkan:
README.md
docs
service-aPerintah git sparse-checkout list menampilkan pilihan yang aktif — hanya dua nama itu, tanpa README.md, karena berkas root diambil otomatis:
docs
service-aStatus index menjelaskan ke mana berkas lainnya pergi. git ls-files -t menandai setiap entri dengan satu huruf:
H README.md
H docs/panduan.md
H service-a/main.go
H service-a/main_test.go
S service-b/main.go
S service-b/router.goHuruf H menandai berkas terlacak normal; huruf S menandai entri ber-skip-worktree — Git mencatatnya tetap ada di index, tetapi berkas fisiknya sengaja tidak dikeluarkan. Inilah sebabnya git status tetap bersih: tidak ada berkas “hilang”, yang ada hanyalah berkas yang dijadwalkan absen. Pola lengkapnya tersimpan di .git/info/sparse-checkout:
/*
!/*/
/docs/
/service-a/Empat baris ini ditulis ulang oleh Git setiap kali set dijalankan, dan cara bacanya persis gaya pola .gitignore
: ambil semua di root (/*), kecuali direktori (!/*/), lalu kembalikan /docs/ dan /service-a/ beserta seluruh isinya. Riwayat tidak ikut terpangkas — git log --oneline | wc -l tetap menghasilkan 2, karena kedua commit monorepo masih utuh di object database.
add dan disable: Menambah Melepas #
Direktori bisa ditambah tanpa mengulang set dari nol. Perintah add menggabungkan pilihan baru ke daftar yang ada:
git sparse-checkout add service-b
ls
git sparse-checkout listOutput yang Dihasilkan (ls):
README.md
docs
service-a
service-bOutput yang Dihasilkan (list):
docs
service-a
service-bPerintah add sendiri tidak mencetak apa pun; dua keluaran di atas adalah bukti efeknya. Kebalikannya, git sparse-checkout disable mematikan mode sparse sepenuhnya dan mengembalikan seluruh working directory. ls kemudian menampilkan README.md, docs, service-a, dan service-b kembali — tanpa satu byte pun diunduh ulang, karena seluruh objek memang sudah ada di .git sejak clone. Ada juga pintasan di sisi klon: git clone --sparse latihan-monorepo klon-sparse menghasilkan klon yang sejak awal hanya berisi berkas root, siap di-set kemudian; ls klon-sparse di sandbox hanya menampilkan README.md.
Pola Non-Cone: Keturunan gitignore #
Mode non-cone — diaktifkan dengan git sparse-checkout set --no-cone — menerima pola bebas bergaya .gitignore seperti *.go atau !service-b/, sehingga berkas bisa dipilih per tipe, bukan per direktori utuh. Kelenturan itu berbanding mahal: Git harus mencocokkan setiap path terhadap pola, dan dokumentasi resmi git sparse-checkout
menandai mode ini deprecated dengan daftar masalah perilaku yang panjang. Untuk kebutuhan umum — pilih direktori, ambil semuanya — cone mode adalah jawaban yang cepat dan cukup.
Sparse Checkout Bukan Partial Clone #
Dua teknik ini sering disebut bersama karena keduanya “mengecilkan clone”, tetapi keduanya memotong di tempat berbeda:
| Aspek | Sparse checkout | Partial clone |
|---|---|---|
| Working directory | Hanya direktori pilihan | Tergantung filter; biasanya lengkap |
| Object database | Utuh sejak clone | Blob diunduh saat dibutuhkan (--filter=blob:none) |
| Riwayat commit | Utuh | Utuh |
| Butuh server pendukung | Tidak — murni lokal | Ya — server harus mendukung filter |
| Beban jaringan clone | Tetap penuh | Menyusut sesuai filter |
Sparse checkout murni urusan lokal: ia menyeleksi apa yang keluar dari object database ke disk, bukan apa yang diunduh. Partial clone menyeleksi objek apa yang ditransfer dari server — topik yang dekat dengan teknik berikutnya. Karena clone dangkal memotong sumbu ketiga, yaitu jumlah riwayat, ketiganya bisa dipakai sendiri-sendiri atau digabung, dan perbandingannya paling jelas dilihat dari sisi ukuran: lanjut ke Shallow Clone .