Runner CI men-clone repository 2 GB enam kali sehari hanya untuk menjalankan test pada commit terbaru; seluruh riwayat sepuluh tahun diunduh setiap kali lalu dibuang. Kebutuhan seperti itu tidak meminta riwayat — hanya snapshot ujung. Shallow clone memotong clone tepat di sumbu itu: ambil N commit terakhir, tinggalkan sisanya di server. Kita akan mengukur penghematannya pada repository berisi artefak besar yang berganti-ganti, membaca tanda grafted yang Git tinggalkan, memperdalam klon bila kebutuhan berubah, dan mencatat batas-batas yang membuat teknik ini bukan jawaban universal.
Repository dengan Riwayat Gemuk #
Repository latihan meniru proyek yang setiap rilis mengganti artefak 1,2 MB secara utuh — tepat pola yang dibedah di File Besar : blob lama hanya hidup di riwayat, sehingga clone penuh membayar untuk keenam versi:
mkdir latihan-riwayat && cd latihan-riwayat
git init -b main
git config user.name "Budi Santoso"
git config user.email "[email protected]"
printf 'proyek demo riwayat\n' > README.md
git add README.md
for i in 1 2 3 4 5 6; do
python3 -c "import random; random.seed(203$i); open('artefak.bin','wb').write(random.randbytes(1200000))"
git add artefak.bin
git commit -m "Rilis artefak v$i"
doneEnam commit rilis menghasilkan enam blob berbeda yang semuanya terjangkau dari main. Sebuah branch fitur-desain dengan satu commit tambahan menyempurnakan gambaran — repository nyata hampir selalu punya lebih dari satu branch.
Jebakan Pertama: –depth Diabaikan pada Clone Lokal #
Insting pertama kita mungkin langsung menjalankan git clone --depth 1 latihan-riwayat klon-gotcha dari direktori induk. Git menolaknya dengan sopan:
Cloning into 'klon-gotcha'...
warning: --depth is ignored in local clones; use file:// instead.
done.Clone dari path lokal mengambil jalur pintas — Git tahu sumbernya ada di disk yang sama sehingga object database cukup di-hardlink tanpa negosiasi protokol; memotong kedalaman tidak bermakna di jalur itu. Solusinya dipaksa melewati protokol transfer biasa dengan skema file://, dan sejak itu --depth dihormati.
Dua Klon: Penuh vs Dangkal #
Pembanding yang adil butuh dua klon lewat file:// — satu tanpa --depth, satu dengan --depth 1:
cd ..
git clone file://latihan-riwayat klon-penuh
git clone --depth 1 file://latihan-riwayat klon-dangkal
du -sh klon-penuh/.git klon-dangkal/.gitOutput yang Dihasilkan:
7.1M klon-penuh/.git
1.4M klon-dangkal/.gitRincian object database mempertegas jurangnya — git count-objects -vH di klon-penuh melaporkan in-pack: 22 dan size-pack: 6.87 MiB, sementara klon-dangkal hanya in-pack: 4 dan size-pack: 1.15 MiB:
| Pengukuran | Klon penuh | Klon dangkal |
|---|---|---|
du -sh .git | 7.1M | 1.4M |
| Objek dalam pack | 22 | 4 |
size-pack | 6.87 MiB | 1.15 MiB |
| Commit terjangkau | 7 (main + fitur-desain) | 1 |
| Waktu transfer | Seluruh riwayat | Hanya ujung |
Angka du bervariasi tipis mengikuti ukuran blok filesystem, tetapi rasionya stabil di mesin mana pun. Empat objek klon dangkal adalah tepat kebutuhan snapshot ujung: blob README.md, blob artefak terbaru, tree root, dan commit v6 — tanpa lima versi artefak yang sudah tergantikan.
Isi Klon Dangkal: grafted dan Berkas shallow #
cd klon-dangkal
git log --oneline --decorate
git rev-list --count HEAD
cat .git/shallowOutput yang Dihasilkan (log):
a02ba0f (grafted, HEAD -> main, origin/main, origin/HEAD) Rilis artefak v6Output yang Dihasilkan:
1Output yang Dihasilkan (isi .git/shallow):
a02ba0fe2504fd69e708bf9d0f80eb7c63f93544Kata grafted pada baris log adalah pengakuan jujur Git: commit v6 sebenarnya memiliki parent v5, tetapi parent itu tidak dimiliki klon, sehingga riwayat “disambung” ke titik henti. Batas sambungan itu dicatat di .git/shallow — berkas ini berisi daftar hash commit yang parent-nya sengaja tidak diambil. Perintah git branch -r menunjukkan pemotongan sumbu kedua:
origin/HEAD -> origin/main
origin/mainHanya origin/main yang ikut — shallow clone secara bawaan juga menjalankan --single-branch, jadi branch fitur-desain tidak diunduh sama sekali. Flag --no-single-branch mengembalikan semua branch (tetap dangkal) bila diperlukan.
Kedalaman Bebas: –depth 3 #
Kedalaman tidak harus satu. git clone --depth 3 file://latihan-riwayat klon-depth3 mengunduh tiga commit terakhir, dan log-nya berisi tepat tiga baris:
a02ba0f Rilis artefak v6
9fa4416 Rilis artefak v5
076b7b3 Rilis artefak v4Semakin dalam kedalaman, semakin banyak blob rilis lama ikut terunduh — angka du tumbuh mengikuti jumlah objek, sehingga --depth adalah tuas antara hemat dan lengkap.
Memperdalam dengan git fetch –unshallow #
Kebutuhan berubah: tiba-tiba kita ingin membaca riwayat penuh dari klon dangkal yang sudah ada. Tidak perlu meng-clone ulang:
git fetch --unshallow
git rev-list --count HEAD
git log --oneline
ls .git/shallowOutput yang Dihasilkan (rev-list):
6Output yang Dihasilkan (log):
a02ba0f Rilis artefak v6
9fa4416 Rilis artefak v5
076b7b3 Rilis artefak v4
211d635 Rilis artefak v3
9b9e565 Rilis artefak v2
911a27b Rilis artefak v1Output yang Dihasilkan (ls):
ls: cannot access '.git/shallow': No such file or directorygit fetch --unshallow sendiri menyelesaikan pekerjaannya tanpa keluaran; buktinya ada pada tiga hasil berikutnya. Jumlah commit naik dari 1 ke 6, log menampilkan seluruh rantai rilis, dan berkas .git/shallow hilang — tanda klon bukan lagi dangkal. du -sh .git kini melaporkan 7.2M, sedikit di atas klon penuh karena objek lama datang sebagai pack tambahan. Bila pemulihan penuh berlebihan, git fetch --depth=3 memperdalam bertahap sesuai angka yang kita pilih.
Keterbatasan dan Kapan Dipakai #
Dalam praktik, shallow clone bersinar di tempat berumur pendek: pipeline CI/CD yang hanya membangun commit terakhir, container image yang membekukan kode, atau mesin build sekali pakai. Kombinasinya pun lazim — --depth 1 --single-branch untuk pipeline, ditambah sparse checkout
bila working directory juga perlu dipangkas, dan --filter=blob:none bila server mendukung partial clone. Semua dokumentasi opsi tersedia di git clone
.
Clone memotong biaya per repository. Kadang kebutuhannya kebalikannya: repository lain justru perlu hadir di dalam repository utama, terpin pada commit tertentu — tugas Submodules .