Logo baru selesai dikerjakan desainer, di-commit, lalu kita penasaran apa yang berubah — dan git diff hanya menjawab satu baris: Binary files a/logo.png and b/logo.png differ. Tidak ada +, tidak ada -, tidak ada petunjuk sama sekali. Perlakuan ini disengaja: alat diff baris-per-baris tidak berarti untuk berkas biner, jadi Git memilih diam. Kabar baiknya, diam bukan satu-satunya pilihan — --numstat tetap mencatat kehadiran berkas biner, --binary mengemas byte-byte-nya menjadi patch yang benar-benar bisa diterapkan, dan driver textconv mengajarkan Git membaca isinya lewat konversi. Chapter ini membedah ketiganya dengan berkas biner kecil sungguhan, lalu menutup dengan pengantar ke masalah yang lebih besar: berkas biner yang ukurannya besar.
Diff Biner Bawaan: Satu Baris “differ” #
Kita siapkan berkas biner mungil yang meniru ciri logo: nomor sihir \x89PNG, teks deskripsi, dan byte NUL di ekor. Dua versi dibuat agar ada yang bisa dibandingkan:
mkdir latihan-biner && cd latihan-biner
git init -b main
git config user.name "Budi Santoso"
git config user.email "[email protected]"
printf '\x89PNG\r\n\x1a\nlogo v1 lebar 64 tinggi 32\n\x00\x00\x00\x0d' > logo.png
git add logo.png
git commit -m "Tambah logo awal"
printf '\x89PNG\r\n\x1a\nlogo v2 lebar 128 tinggi 64\n\x00\x00\x00\x0d' > logo.png
git diffOutput yang Dihasilkan:
diff --git a/logo.png b/logo.png
index 9751028..64834cf 100644
Binary files a/logo.png and b/logo.png differBaris Binary files a/logo.png and b/logo.png differ menggantikan seluruh hunk. Vonis “biner” jatuh dari heuristik sederhana: Git memeriksa potongan awal berkas (8.000 byte pertama), dan kehadiran satu byte NUL (\x00) di sana sudah cukup. Konsekuensinya berlaku dua arah — berkas teks yang kebetulan memuat NUL ikut diperlakukan biner, dan berkas tanpa NUL dibedah baris demi baris meski ekstensinya .png.
Statistik ringkas pun menyerah:
git diff --numstatOutput yang Dihasilkan:
- - logo.pngDua kolom hitungan baris diganti tanda - — biner tidak dihitung per baris. Format ini justru berguna ketika menyorot berkas teks di antara banyak perubahan: baris - - logo.png tetap terlihat lompong tanpa mengaburkan angka berkas lain.
–binary: Patch Biner yang Bisa Diterapkan #
Teks tak terbaca bukan berarti byte tak tersentuh. Opsi --binary mengemas isi berkas lama dan baru ke dalam format patch sehingga perubahan biner bisa dikirim sebagai berkas teks dan diterapkan kembali:
git diff --binaryOutput yang Dihasilkan:
diff --git a/logo.png b/logo.png
index 9751028b1a0645ac63bab6bd5d67534e51f918d7..64834cf8a51db96328fa170c8a2c35f7f4370845 100644
GIT binary patch
literal 40
vcmeAS@N?(olH$tAPtR8<Gg8P&O-d|MFf_7ID9OxAPtQ~^GvQ)jVBiG+=Pe3H
literal 39
ucmeAS@N?(olH$tAPtR8<GgQb)O-d|MFf&mo$;?Yn&r~or;$mQ6-~|BP910KsKita bedah strukturnya:
GIT binary patch— penanda bahwa hunk berikut membawa isi berkas, bukan baris teks.literal 40— panjang berkas hasil (versi v2, 40 byte), diikuti datanya yang terenkode base85 agar aman dikirim sebagai patch teks.literal 39— pasangan baliknya: berkas sebelumnya (39 byte) supaya patch juga bisa dibalikkan.
Bukti bahwa format ini benar-benar hidup: simpan keluarannya ke berkas, pulihkan logo ke versi lama, lalu terapkan:
git diff --binary > tambalan-logo.patch
git checkout -- logo.png
git status --short
git apply tambalan-logo.patch
git status --shortOutput yang Dihasilkan:
?? tambalan-logo.patchOutput yang Dihasilkan:
M logo.png
?? tambalan-logo.patchSebelum git apply, hanya tambalan-logo.patch yang untracked dan logo.png bersih; setelahnya logo.png berstatus M — byte versi v2 direkonstruksi dari blok literal tanpa berkas aslinya pernah dikirim. Pola checkout -- lalu apply inilah yang dipakai saat berkolaborasi lewat patch, misalnya mengirim tambalan lewat surel.
textconv: Membaca Isi Biner Lewat Konversi #
--binary memindahkan byte, bukan maknanya. Untuk membuat diff terbaca, kita mendaftarkan konversi sehingga diff berjalan pada hasil konversi berkas, bukan byte mentahnya. Mekanismenya dua potong: baris di .gitattributes memetakan pola berkas ke nama driver, dan konfigurasi diff.<driver>.textconv menentukan perintah konversinya:
*.png diff=tekslogogit config diff.tekslogo.textconv strings
git diffOutput yang Dihasilkan:
diff --git a/logo.png b/logo.png
index 9751028..64834cf 100644
--- a/logo.png
+++ b/logo.png
@@ -1 +1 @@
-logo v1 lebar 64 tinggi 32
+logo v2 lebar 128 tinggi 64Diff tiba-tiba terbaca: -logo v1 lebar 64 tinggi 32 berganti +logo v2 lebar 128 tinggi 64. Untuk kedua versi, Git menjalankan strings — alat yang mengekstrak rangkaian karakter tercetak dari berkas biner — lalu membedah keluarannya sebagai teks. Verifikasi singkat memperlihatkan sumber baris itu:
strings logo.pngOutput yang Dihasilkan:
logo v2 lebar 128 tinggi 64Pilihan perintah konversi bebas selama membaca berkas dan mencetak teks: od -c (dump byte per karakter) untuk format yang strukturnya penting, atau alat khusus seperti pembaca metadata video — asalkan terpasang di mesin. Pada sandbox ini strings terbukti bekerja, jadi itulah yang dipakai. Satu catatan urutan penting: --binary dan textconv saling meniadakan — begitu driver aktif, git diff memilih hasil konversi, sehingga penulisan GIT binary patch pada sesi sebelumnya dikerjakan sebelum konfigurasi ini ada.
Atribut dan konfigurasinya kita simpan sebagai penutup latihan:
git add logo.png .gitattributes
git commit -m "Perbarui logo dan aktifkan driver diff teks"Output yang Dihasilkan:
[main 5efb708] Perbarui logo dan aktifkan driver diff teks
2 files changed, 1 insertion(+)
create mode 100644 .gitattributesOpsi-opsi diff untuk berkas biner dirangkum berikut:
| Perintah | Hasil untuk berkas biner |
|---|---|
git diff | Binary files a/... and b/... differ |
git diff --numstat | - - path (tanpa hitungan baris) |
git diff --binary | GIT binary patch siap git apply |
git diff + textconv | diff teks hasil konversi |
Biner kecil seperti logo 40 byte tidak menimbulkan masalah; Git bahkan mengemasnya dan memperlakukan diffnya dengan sopan. Persoalan dimulai ketika berkasnya besar: setiap revisi logo, video, atau model AI tersimpan penuh sebagai blob — 10 revisi berarti 10 salinan utuh, dan repository membengkak meski isinya hanya bergeser sedikit. Untuk itulah Git menyediakan strategi berkas besar dan Git LFS . Lanjut ke File Besar .