Kolaborator baru join, menjalankan git clone, lalu menunggu — dan menunggu, dan menunggu. Setelah 700 MB terunduh barulah ketahuan penyebabnya: repository menyimpan ratusan versi berkas video yang masing-masing utuh. Inilah sifat paling kejam dari berkas besar di Git: masalahnya bukan sekali waktu, melainkan permanen — selama blob tersebut ada di riwayat, setiap clone, fetch, dan CI baru membayar ongkos yang sama. Chapter ini membedah mengapa ukurannya menumpuk, cara mengukur blob terbesar dengan alat bawaan Git, lalu aturan pencegahan sebelum kita melanjutkan ke solusi khusus: Git LFS.
Setiap Versi Tersimpan Utuh Sebagai Blob #
Git adalah penyimpan snapshot, bukan delta: satu commit menyimpan seluruh isi berkas pada saat itu, dan revisi berikutnya menyimpan salinan utuh lagi — kompresi hanya bekerja dalam satu pack, tidak lintas versi untuk berkas acak/binary. Kita buktikan dengan berkas 5 MB yang dibuat dari data acak (acak dipilih agar tidak termampatkan, seperti rekaman video sungguhan). Bilangan acak dibangkitkan dengan benih tetap agar hasilnya identik antar mesin:
mkdir latihan-besar && cd latihan-besar
git init -b main
git config user.name "Budi Santoso"
git config user.email "[email protected]"
python3 -c "import random; random.seed(2026); open('rekaman-demo.mp4','wb').write(random.randbytes(5000000))"
git add rekaman-demo.mp4
git commit -m "Tambah rekaman demo"
git count-objects -vHOutput yang Dihasilkan:
count: 3
size: 4.78 MiB
in-pack: 0
packs: 0
size-pack: 0 bytes
prune-packable: 0
garbage: 0
size-garbage: 0 bytesPerintah git count-objects -vH
menghitung isi object database; dua kolom kuncinya: count = jumlah objek longgar (loose), dan size = total ukurannya dalam format yang terbaca manusia (-H). Tiga objek pertama adalah blob rekaman, tree, dan commit — hampir seluruh 4,78 MiB berasal dari satu blob itu. Sekarang kita ganti seluruh isinya dengan versi kedua dan commit lagi:
python3 -c "import random; random.seed(2027); open('rekaman-demo.mp4','wb').write(random.randbytes(5000000))"
git add rekaman-demo.mp4
git commit -m "Rekam ulang demo versi kedua"
git count-objects -vH
git gc
git count-objects -vHOutput yang Dihasilkan:
count: 6
size: 9.56 MiBOutput yang Dihasilkan:
count: 0
size: 0 bytes
in-pack: 6
packs: 1
size-pack: 9.54 MiB
prune-packable: 0
garbage: 0
size-garbage: 0 bytesBerkas yang diubah sedikit saja pun menambah ukuran penuh. Tiga objek baru muncul sehingga total menjadi enam, dan size melipat dua menjadi 9,56 MiB — meski isi berkas hanya berganti. git gc lalu memadatkan keenam objek ke satu pack (in-pack: 6, size-pack: 9.54 MiB), dan pack tetap sebesar itu: kompresi zlib tidak bisa menyatukan dua blob acak yang isinya berbeda total. Sepuluh revisi video berarti sepuluh salinan — persis pola yang diperkenalkan di File Biner dan Diff
.
Clone Mengunduh Semua Versi, Bukan Hanya Terbaru #
Working directory hanya memuat satu berkas 5 MB, jadi mungkin terasa wajar mengira clone sebesar itu juga. Kenyataannya:
cd ..
git clone latihan-besar klon-besar
du -sh klon-besar/.git
stat -c '%s %n' klon-besar/rekaman-demo.mp4Output yang Dihasilkan:
9.8M klon-besar/.git
5000000 klon-besar/rekaman-demo.mp4Direktori .git klon berukuran 9,8M — hampir dua kali isi working directory-nya. Clone memindahkan seluruh object database yang relevan dengan riwayat: kedua versi rekaman ikut terunduh karena keduanya dirujuk commit di main. git fetch dan git pull teratur kemudian hanya menambah objek baru, tetapi setiap anggota tim baru, setiap runner CI, dan setiap salinan kerja baru harus membayar 9,8M ini dari nol. Angka di mesin kita mungkin sedikit berbeda karena ukuran blok filesystem, tetapi rasionya konsisten.
Mengukur Blob Terbesar di Riwayat #
Sebelum mengobati, kita perlu mendiagnosis. Ukuran working directory bisa dicek cepat lewat du:
git ls-files | xargs -d '\n' du -chOutput yang Dihasilkan:
4.8M rekaman-demo.mp4
4.8M totalgit ls-files mencetak daftar berkas terlacak; xargs -d '\n' meneruskannya aman dari spasi di nama; du -ch menjumlahkan dan menutup dengan total. Namun pengukuran ini buta terhadap riwayat — versi lama yang sudah dihapus dari working directory tidak terlihat. Untuk mengintip seluruh object database, kita pasangkan git rev-list --objects --all (mencari setiap objek dirujuk refs mana pun, lengkap dengan path-nya) dengan git cat-file --batch-check (membaca tipe, hash, dan ukuran tiap objek tanpa mengunduh isinya):
git rev-list --objects --all \
| git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' \
| awk '/^blob/ {print $3, $4}' \
| sort -rn | head -n 5Output yang Dihasilkan:
5000000 rekaman-demo.mp4
5000000 rekaman-demo.mp4Dua baris untuk satu nama berkas: dua blob berukuran 5.000.000 byte — versi pertama dan kedua, keduanya masih hidup di riwayat. Inilah alat diagnosis utama saat repository terasa gemuk: jalankan di repo proyek nyata, dan daftar blob terbesar segera menunjuk biang keroknya.
Dampak dan Pencegahan #
Dampaknya menumpuk di banyak tempat sekaligus:
| Aspek | Dampak berkas besar di riwayat |
|---|---|
git clone | Mengunduh semua versi, bukan hanya terbaru — makin banyak revisi makin lambat |
git fetch / git pull | Objek baru ikut di-pack; transfer rutin jadi berat |
| CI/CD | Setiap pipeline men-clone ulang; menit-menit hangat terbuang di tiap build |
| Penyimpanan | Server hosting dan setiap mesin anggota tim menyimpan salinan penuh |
| Tooling | git status, gc, dan operasi index melambat pada tree raksasa |
Pencegahan selalu lebih murah daripada pengobatan. GitHub menolak berkas di atas 100 MB per berkas dan memberi peringatan mulai 50 MB — angka yang layak dijadikan ambang praktis: di atas itu, pertimbangkan Git LFS
yang kita bahas di chapter berikutnya (kebijakan lengkapnya di dokumentasi GitHub
). Kebiasaan yang paling berdampak: siapkan .gitignore
sejak commit pertama — build, dependensi, dan berkas hasil ekspor tidak pernah masuk riwayat sejak awal. Disiplin ukuran commit juga membantu: periksa dengan git count-objects -vH atau du sebelum push kalau ragu.
Bila berkas besar memang bagian sah dari proyek — aset game, model AI, video — mengabaikannya bukan pilihan. Git punya mekanisme khusus yang menyimpan isi di luar object database: pointer kecil di repository, berkas asli di penyimpanan LFS. Lanjut ke Git LFS .