"Diff" adalah lingua franca perubahan. Mereka adalah narasi ringkas yang memberi tahu Anda apa yang berpindah di antara dua versi suatu hal—kode sumber, prosa, kumpulan data—tanpa memaksa Anda membaca ulang semuanya. Di balik beberapa simbol itu (+, -, @@) terdapat tumpukan algoritme, heuristik, dan format yang dalam yang menyeimbangkan optimalitas, kecepatan, dan pemahaman manusia. Artikel ini adalah tur praktis, dari algoritme ke alur kerja, tentang diff: bagaimana mereka dihitung, bagaimana mereka diformat, bagaimana alat penggabungan menggunakannya, dan bagaimana cara menyetelnya untuk ulasan yang lebih baik. Sepanjang jalan, kami akan mendasarkan klaim pada sumber primer dan dokumen resmi—karena detail kecil (seperti apakah spasi dihitung) sangat penting.
Secara formal, diff mendeskripsikan skrip edit terpendek (SES) untuk mengubah urutan "lama" menjadi "baru" menggunakan penyisipan dan penghapusan (dan terkadang substitusi, yang dapat dimodelkan sebagai hapus+sisip). Dalam praktiknya, sebagian besar diff yang dihadapi programmer adalahberorientasi baris dan kemudian secara opsional disempurnakan menjadi kata atau karakter untuk keterbacaan. Keluaran kanonis adalah format konteks dan terpadu ; yang terakhir—yang biasa Anda lihat dalam tinjauan kode—memadatkan keluaran dengan header ringkas dan "hunks", masing-masing menunjukkan lingkungan konteks di sekitar perubahan. Format terpadu dipilih melalui -u/--unified dan merupakan standar de-facto untuk menambal; patch umumnya mendapat manfaat dari baris konteks untuk menerapkan perubahan secara kuat.
Manual GNU diff membuat katalog sakelar yang Anda jangkau ketika Anda menginginkan lebih sedikit noise dan lebih banyak sinyal—mengabaikan spasi, memperluas tab untuk penyelarasan, atau meminta skrip edit "minimal" meskipun lebih lambat (referensi opsi). Opsi-opsi ini tidak mengubah apa artinya dua file berbeda; mereka mengubah seberapa agresif algoritme mencari skrip yang lebih kecil dan bagaimana hasilnyadisajikan kepada manusia.
Sebagian besar diff teks dibangun di atas abstraksi Subsekuens Umum Terpanjang (LCS) . Pemrograman dinamis klasik memecahkan LCS dalam waktu dan ruang O(mn), tetapi itu terlalu lambat dan haus memori untuk file besar. Algoritma Hirschberg menunjukkan cara menghitung perataan optimal dalam ruang linier (masih waktu O(mn)) menggunakan divide-and-conquer, teknik penghematan ruang mendasar yang memengaruhi implementasi diff praktis.
Untuk kecepatan dan kualitas, terobosannya adalah algoritma Eugene W. Myers tahun 1986, yang menemukan SES dalam waktu O(ND) (N ≈ total baris, D ≈ jarak edit) dan ruang mendekati linier. Myers memodelkan editan dalam "grafik edit" dan maju di sepanjang batas paling jauh, menghasilkan hasil yang cepat dan mendekati minimal dalam pengaturan diff baris. Itulah mengapa "Myers" tetap menjadi default di banyak alat.
Ada juga keluarga Hunt–Szymanski , yang mempercepat LCS ketika beberapa posisi cocok (dengan pra-pengindeksan kecocokan dan mengejar subsekuens yang meningkat), dan secara historis terkait dengan varian diff awal. Algoritma-algoritma ini menerangi trade-off: dalam input dengan kecocokan yang jarang, mereka dapat berjalan sub-kuadrat. Untuk tinjauan praktisi yang menjembatani teori dan implementasi, lihat catatan Neil Fraser.
Myers bertujuan untuk skrip edit minimal, tetapi "minimal" ≠ "paling mudah dibaca". Blok besar yang diatur ulang atau digandakan dapat menipu algoritme SES murni menjadi perataan yang canggung. Masuklah patience diff, yang dikaitkan dengan Bram Cohen: ia berlabuh pada baris unik, frekuensi rendah untuk menstabilkan perataan, seringkali menghasilkan diff yang menurut manusia lebih bersih—terutama dalam kode dengan fungsi yang dipindahkan atau blok yang diatur ulang. Banyak alat mengekspos ini melalui opsi "kesabaran" (misalnya,diff.algorithm).
Histogram diff memperluas kesabaran dengan histogram frekuensi untuk menangani elemen berfrekuensi rendah dengan lebih baik sambil tetap cepat (dipopulerkan di JGit). Jika Anda pernah menemukan --histogram menghasilkan hunks yang lebih jelas untuk file yang berisik, itu memang disengaja. Di Git modern, Anda dapat memilih algoritme secara global atau per-panggilan:git config diff.algorithm myers|patience|histogram atau git diff --patience.
Diff baris ringkas tetapi dapat mengaburkan editan kecil. Diff tingkat kata (--word-diff) mewarnai perubahan intra-baris tanpa membanjiri ulasan dengan penyisipan/penghapusan seluruh baris—bagus untuk prosa, string panjang, atau satu baris.
Spasi dapat membanjiri diff setelah pemformatan ulang. Git dan GNU diff keduanya memungkinkan Anda mengabaikan perubahan spasi dalam berbagai tingkat dan opsi spasi GNU diff (-b, -w, -B) membantu saat pemformat berjalan; Anda akan melihat editan logis alih-alih noise perataan.
Ketika kode dipindahkan secara grosir, Git dapat menyorot blok yang dipindahkan dengan --color-moved, secara visual memisahkan "dipindahkan" dari "diubah", yang membantu peninjau mengaudit bahwa pemindahan tidak menyembunyikan editan yang tidak diinginkan. Pertahankan melalui diff.colorMoved.
diff3Diff dua arah membandingkan tepat dua versi; ia tidak dapat mengetahui apakah kedua sisi mengedit baris dasar yang sama, sehingga seringkali terlalu banyak konflik. Penggabungan tiga arah (digunakan oleh VCS modern) menghitung diff dari leluhur bersamake setiap sisi dan kemudian merekonsiliasi kedua set perubahan. Ini secara dramatis mengurangi konflik palsu dan memberikan konteks yang lebih baik. Inti algoritmik klasik di sini adalah diff3, yang menggabungkan perubahan dari "O" (dasar) ke "A" dan "B" dan menandai konflik jika perlu.
Pekerjaan akademis dan industri terus memformalkan dan meningkatkan kebenaran penggabungan; misalnya, penggabungan tiga arah terverifikasi mengusulkan gagasan semantik kebebasan konflik. Dalam Git sehari-hari, strategi penggabungan ort modern dibangun di atas diffing dan deteksi penggantian nama untuk menghasilkan penggabungan dengan lebih sedikit kejutan. Bagi pengguna, tips utamanya adalah: tampilkan baris dasar dalam konflik dengan merge.conflictStyle=diff3, dan sering-seringlah berintegrasi agar diff tetap kecil.
Diff tradisional tidak dapat "melihat" penggantian nama karena pengalamatan konten memperlakukan file sebagai blob; mereka hanya melihat penghapusan dan penambahan. Heuristik deteksi penggantian nama menjembatani kesenjangan itu dengan membandingkan kesamaan di seluruh pasangan yang ditambahkan/dihapus. Di Git, aktifkan atau setel melalui -M/--find-renames[=<n>] (defaultnya adalah ~50% kesamaan). Turunkan untuk pemindahan yang lebih berisik. Anda dapat membatasi perbandingan kandidat dengan diff.renameLimit (dan merge.renameLimit selama penggabungan). Untuk mengikuti riwayat di seluruh penggantian nama, gunakan git log --follow -- <path>. Git terbaru juga melakukan deteksi penggantian nama direktori untuk menyebarkan pemindahan folder selama penggabungan.
Teks bukan satu-satunya yang berubah. Untuk biner, Anda biasanya menginginkan pengkodean delta—mengeluarkan instruksi salin/tambah untuk merekonstruksi target dari sumber. Algoritma rsync merintis diferensiasi jarak jauh yang efisien menggunakan checksum bergulir untuk menyelaraskan blok di seluruh jaringan, meminimalkan bandwidth.
IETF menstandarkan format delta generik, VCDIFF (RFC 3284), yang menjelaskan bytecode dari ADD, COPY, dan RUN, dengan implementasi seperti xdelta3 menggunakannya untuk menambal biner. Untuk tambalan ringkas pada file yang dapat dieksekusi, bsdiff seringkali menghasilkan delta yang sangat kecil melalui larik akhiran dan kompresi; pilih saat ukuran tambalan mendominasi dan pembuatan dapat terjadi secara offline.
Ketika Anda membutuhkan penambalan yang kuat dalam menghadapi editan bersamaan atau konteks yang sedikit tidak selaras—pikirkan editor atau sistem kolaboratif—pertimbangkan diff-match-patch. Ini menggabungkan diferensiasi gaya Myers dengan Bitap pencocokan fuzzy untuk menemukan kecocokan dekat dan menerapkan tambalan "sebaik mungkin", ditambah percepatan pra-diff dan pembersihan pasca-diff yang menukar sedikit minimalitas untuk keluaran manusia yang lebih bagus. Untuk cara menggabungkan diff dan tambalan fuzzy dalam loop sinkronisasi berkelanjutan, lihat Sinkronisasi DiferensialFraser.
Diff baris pada CSV/TSV rapuh karena perubahan satu sel dapat terlihat seperti editan seluruh baris. Alat diff yang sadar tabel (daff) memperlakukan data sebagai baris/kolom, mengeluarkan tambalan yang menargetkan sel tertentu dan merender visualisasi yang membuat penambahan, penghapusan, dan modifikasi menjadi jelas (lihat vignette R). Untuk pemeriksaan cepat, pembeda CSV khusus dapat menyorot perubahan sel demi sel dan pergeseran tipe; mereka tidak eksotis secara algoritmik, tetapi mereka meningkatkan sinyal ulasan dengan membandingkan struktur yang sebenarnya Anda pedulikan.
--patience jika penyusunan ulang atau blok yang berisik membingungkan output, atau --histogram untuk diff yang cepat dan dapat dibaca pada teks berulang. Tetapkan default dengan git config diff.algorithm ….-b, -w, --ignore-blank-lines) untuk fokus pada perubahan substantif. Di luar Git, lihat kontrol spasi GNU diff.--word-diff membantu untuk baris panjang dan prosa.--color-moved (atau diff.colorMoved) memisahkan "dipindahkan" dari "diubah".-M atau sesuaikan ambang batas kesamaan (-M90%, -M30%) untuk menangkap penggantian nama; ingat defaultnya sekitar 50%. Untuk pohon yang dalam, atur diff.renameLimit.git log --follow -- <path>.Penggabungan menghitung dua diff (BASE→OURS, BASE→THEIRS) dan mencoba menerapkan keduanya ke BASE. Strategi seperti ort mengatur ini dalam skala besar, melipat dalam deteksi penggantian nama (termasuk pemindahan skala direktori) dan heuristik untuk meminimalkan konflik. Ketika konflik terjadi, --conflict=diff3 memperkaya penanda dengan konteks dasar, yang sangat berharga untuk memahami niat. Bab Pro Git tentang Penggabungan Lanjutan menjelaskan pola resolusi, dan dokumen Git mencantumkan kenop seperti -X ours dan -X theirs. Untuk menghemat waktu pada konflik yang berulang, aktifkan rerere untuk merekam dan memutar ulang resolusi Anda.
Jika Anda menyinkronkan aset besar melalui jaringan, Anda lebih dekat ke rsync dunia daripada diff lokal. Rsync menghitung checksum bergulir untuk menemukan blok yang cocok dari jarak jauh, lalu hanya mentransfer apa yang diperlukan. Untuk delta yang dikemas, VCDIFF/xdelta memberi Anda bytecode standar dan alat yang matang; pilih saat Anda mengontrol encoder dan decoder. Dan jika ukuran tambalan sangat penting (misalnya, firmware over-the-air), bsdiff menukar CPU/memori pada waktu pembuatan untuk tambalan yang sangat kecil.
Pustaka seperti diff-match-patch menerima bahwa, di dunia nyata, file yang Anda tambal mungkin telah bergeser. Dengan menggabungkan diff yang solid (seringkali Myers) dengan pencocokan fuzzy (Bitap) dan aturan pembersihan yang dapat dikonfigurasi, mereka dapat menemukan tempat yang tepat untuk menerapkan tambalan dan membuat diff lebih mudah dibaca—penting untuk pengeditan dan sinkronisasi kolaboratif.
-u/-U<n>) ringkas dan ramah tambalan; itulah yang diharapkan oleh tinjauan kode dan CI (referensi).git diff; opsi spasi GNU).diff3 -gaya kurang membingungkan; ort plus deteksi penggantian nama mengurangi churn; rerere menghemat waktu.Karena memori otot itu penting:
# Tampilkan diff terpadu standar dengan konteks ekstra
git diff -U5
diff -u -U5 a b
# Dapatkan kejelasan tingkat kata untuk baris panjang atau prosa
git diff --word-diff
# Abaikan noise spasi setelah pemformatan ulang
git diff -b -w --ignore-blank-lines
diff -b -w -B a b
# Sorot kode yang dipindahkan selama peninjauan
git diff --color-moved
git config --global diff.colorMoved default
# Jinakkan refactor dengan deteksi penggantian nama dan ikuti riwayat di seluruh penggantian nama
git diff -M
git log --follow -- <file>
# Pilih algoritme untuk keterbacaan
git diff --patience
git diff --histogram
git config --global diff.algorithm patience
# Lihat baris dasar di penanda konflik
git config --global merge.conflictStyle diff3Diff yang hebat lebih sedikit tentang membuktikan minimalitas dan lebih banyak tentang memaksimalkan pemahaman peninjau dengan biaya kognitif minimum. Itulah sebabnya ekosistem mengembangkan beberapa algoritme (Myers, kesabaran, histogram), beberapa presentasi (terpadu, word-diff, color-moved), dan alat yang sadar domain (daff untuk tabel, xdelta/bsdiff untuk biner). Pelajari trade-off, setel kenop, dan Anda akan menghabiskan lebih banyak waktu untuk bernalar tentang niat dan lebih sedikit waktu untuk menyusun kembali konteks dari baris merah dan hijau.
diff3 • opsi spasiDiff adalah alat atau fungsi yang digunakan dalam sistem kontrol versi untuk menyoroti perbedaan antara dua versi atau instance dari file. Biasanya digunakan untuk melacak perubahan atau pembaruan yang dilakukan pada file dari waktu ke waktu.
Diff membandingkan dua file baris per baris. Ia memindai dan mencocokkan setiap baris di file pertama dengan pasangannya di file kedua, mencatat semua perbedaan signifikan seperti penambahan, penghapusan, atau perubahan.
Patch adalah file yang berisi perbedaan antara dua file, yang diproduksi oleh alat diff. Ini dapat diterapkan ke versi file dengan perintah 'patch' untuk memperbaruinya ke versi yang lebih baru.
Diff seragam adalah jenis format file diff yang menampilkan perubahan dalam format file yang cocok untuk file teks. Menampilkan penghapusan dari file asli diawali dengan '-', dan penambahan pada file asli diawali dengan '+'.
Diff penting dalam sistem kontrol versi karena mereka memungkinkan tim untuk melacak perubahan yang dibuat pada file sepanjang waktu. Pelacakan ini memudahkan pemeliharaan konsistensi, mencegah duplikasi pekerjaan, menemukan kesalahan atau ketidaksesuaian, dan mengelola beberapa versi file dengan efisien.
Algoritma Longest Common Subsequence (LCS) adalah metode umum yang digunakan dalam alat diff untuk menemukan urutan karakter terpanjang yang muncul dari kiri ke kanan di kedua file asli dan modifikasi. Algoritma ini membantu mengidentifikasi kemiripan dan perbedaan utama antara dua file.
Sebagian besar alat diff dasar hanya dapat membandingkan file teks. Namun, alat diff khusus dirancang untuk membandingkan file biner, menampilkan perbedaan dalam format yang dapat dibaca.
Beberapa alat diff paling populer termasuk GNU diff, DiffMerge, KDiff3, WinMerge (Windows), dan FileMerge (Mac). Banyak Lingkungan Pengembangan Terpadu (IDE) juga mencakup utilitas diff bawaan.
Di Git, Anda dapat membuat diff dengan menggunakan perintah `git diff` diikuti oleh dua versi file yang ingin Anda bandingkan. Output akan menunjukkan perbedaan antara dua file tersebut.
Ya, banyak alat diff memiliki kemampuan untuk membandingkan direktori selain file individual. Fitur ini bisa sangat berguna saat membandingkan versi proyek besar dengan banyak file.