Bandingkan dua file

Tanpa batas file. Perbandingan real-time. Gratis, selamanya.
Asli
Diubah

Pribadi dan aman

Semuanya terjadi di browser Anda. File Anda tidak pernah menyentuh server kami.

Sangat cepat

Tanpa mengunggah, tanpa menunggu. Konversi saat Anda meletakkan file.

Benar-benar gratis

Tidak perlu akun. Tidak ada biaya tersembunyi. Tidak ada trik ukuran file.

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

Apa sebenarnya "diff" itu

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.

Dari LCS ke Myers: bagaimana diff dihitung

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.

Ketika "optimal" tidak dapat dibaca: strategi kesabaran dan histogram

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.

Kejelasan tingkat kata, kontrol spasi, dan penyorotan kode yang dipindahkan

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.

Diff dalam layanan penggabungan: dua arah vs. tiga arah dan diff3

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

Deteksi penggantian nama dan ambang batasnya

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.

Diff biner dan delta: rsync, VCDIFF/xdelta, bsdiff

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.

Diff teks di luar kode sumber: pencocokan fuzzy dan penambalan

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 data terstruktur: tabel dan pohon

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.

Penyetelan Git diff praktis: daftar periksa peninjau

  • Pilih algoritme yang tepat: mulai dengan Myers (default), coba --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 ….
  • Kurangi noise: untuk editan gaya saja, gunakan flag spasi (-b, -w, --ignore-blank-lines) untuk fokus pada perubahan substantif. Di luar Git, lihat kontrol spasi GNU diff.
  • Lihat di dalam baris: --word-diff membantu untuk baris panjang dan prosa.
  • Audit kode yang dipindahkan: --color-moved (atau diff.colorMoved) memisahkan "dipindahkan" dari "diubah".
  • Tangani penggantian nama: saat meninjau refactor, tambahkan -M atau sesuaikan ambang batas kesamaan (-M90%, -M30%) untuk menangkap penggantian nama; ingat defaultnya sekitar 50%. Untuk pohon yang dalam, atur diff.renameLimit.
  • Ikuti riwayat di seluruh penggantian nama: git log --follow -- <path>.

Bagaimana penggabungan sebenarnya menggunakan diff (dan apa yang harus dilakukan jika tidak)

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.

Di luar file: skenario jarak jauh dan inkremental

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.

Sepatah kata tentang "fuzzy" dan "ramah"

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.

"Taruhan meja" yang harus Anda internalisasi

  1. Ketahui format Anda. Diff terpadu (-u/-U<n>) ringkas dan ramah tambalan; itulah yang diharapkan oleh tinjauan kode dan CI (referensi).
  2. Ketahui algoritme Anda. Myers untuk editan minimal cepat (makalah); kesabaran/histogram untuk keterbacaan pada penyusunan ulang atau blok yang berisik (kesabaran, histogram); Hirschberg untuk trik ruang linier (makalah); Hunt–Szymanski untuk percepatan kecocokan jarang (makalah).
  3. Ketahui sakelar Anda. Kontrol spasi, word-diff, dan color-moved adalah pengganda ulasan (dokumen git diff; opsi spasi GNU).
  4. Ketahui penggabungan Anda. Tiga arah dengan diff3 -gaya kurang membingungkan; ort plus deteksi penggantian nama mengurangi churn; rerere menghemat waktu.
  5. Pilih alat yang tepat untuk data. Untuk CSV/tabel, gunakan daff; untuk biner, gunakan VCDIFF/xdelta atau bsdiff.

Lampiran: buku masak perintah kecil

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 diff3

Pikiran penutup

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


Referensi pilihan & bacaan lebih lanjut

Pertanyaan yang Sering Diajukan

Apa itu diff?

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

Bagaimana diff membandingkan dua file?

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.

Apa yang dimaksud dengan patch dalam konteks diff?

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.

Apa itu diff seragam?

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 '+'.

Mengapa diff penting dalam sistem kontrol versi?

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.

Apa itu algoritma LCS dalam alat diff?

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.

Apakah alat diff dapat membandingkan file biner?

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.

Apa saja alat diff umum yang digunakan saat ini?

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.

Bagaimana cara membuat diff di Git?

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.

Bisakah saya menggunakan alat diff dengan direktori, bukan hanya file?

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.