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:

bash
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"
done

Enam 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:

text
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:

bash
cd ..
git clone file://latihan-riwayat klon-penuh
git clone --depth 1 file://latihan-riwayat klon-dangkal
du -sh klon-penuh/.git klon-dangkal/.git

Output yang Dihasilkan:

text
7.1M    klon-penuh/.git
1.4M    klon-dangkal/.git

Rincian 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:

PengukuranKlon penuhKlon dangkal
du -sh .git7.1M1.4M
Objek dalam pack224
size-pack6.87 MiB1.15 MiB
Commit terjangkau7 (main + fitur-desain)1
Waktu transferSeluruh riwayatHanya 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 #

bash
cd klon-dangkal
git log --oneline --decorate
git rev-list --count HEAD
cat .git/shallow

Output yang Dihasilkan (log):

text
a02ba0f (grafted, HEAD -> main, origin/main, origin/HEAD) Rilis artefak v6

Output yang Dihasilkan:

text
1

Output yang Dihasilkan (isi .git/shallow):

text
a02ba0fe2504fd69e708bf9d0f80eb7c63f93544

Kata 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:

text
  origin/HEAD -> origin/main
  origin/main

Hanya 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:

text
a02ba0f Rilis artefak v6
9fa4416 Rilis artefak v5
076b7b3 Rilis artefak v4

Semakin 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:

bash
git fetch --unshallow
git rev-list --count HEAD
git log --oneline
ls .git/shallow

Output yang Dihasilkan (rev-list):

text
6

Output yang Dihasilkan (log):

text
a02ba0f Rilis artefak v6
9fa4416 Rilis artefak v5
076b7b3 Rilis artefak v4
211d635 Rilis artefak v3
9b9e565 Rilis artefak v2
911a27b Rilis artefak v1

Output yang Dihasilkan (ls):

text
ls: cannot access '.git/shallow': No such file or directory

git 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 .