Text Diff online: iki metni karşılaştır (algoritma + 6 senaryo)
Bir text diff aracı tek bir soruyu hızla yanıtlar: A sürümü ile B sürümü arasında gerçekten ne değişti? İki metin bloğu yapıştırırsınız, araç bir Longest Common Subsequence algoritması çalıştırır ve her ekleme, silme, düzenleme için yan yana ya da unified bir görünüm elde edersiniz; genellikle bir milisaniyenin altında.
Bu rehber code review yapan geliştiriciler, log dilimlerini karşılaştıran SRE’ler, sözleşmeleri kırmızı kalemle inceleyen avukatlar ve revizyonları gözden geçiren yazarlar içindir. Algoritmayı (LCS, Myers, Patience), iki standart görünümü, “her şey değişmiş gibi görünüyor” şikâyetlerinin %95’ini çözen yoksayma seçeneklerini, ne zaman JSON diff’e geçileceğini, kopyala-yapıştır altı senaryoyu ve algoritmanın kendisinin açıkladığı tuzakları ele alır.
İki metni doğrudan karşılaştırmak istiyorsanız Metin Karşılaştırma aracını açın; tamamen tarayıcınızda çalışır, hiçbir yükleme yapılmaz.
1. Text diff nedir?
Bir text diff, bir metni diğerine dönüştüren en küçük ekleme ve silme kümesidir; her satır eklenmiş, silinmiş ya da değişmemiş olarak işaretlenir. Modern diff’ler kelime veya karakter düzeyinde ikinci bir geçiş ekler, böylece tek karakterlik bir düzenleme tüm satır yerine yalnızca o token’ı vurgular.
1.1 Karakter eşitliğinin (===) neden yeterli olmadığı
200 satırlık bir yapılandırma dosyasının başına bir satır ekleyin ve naif bir karakter karşılaştırması, ekleme noktasından sonraki her byte’ı farklı olarak raporlar. Metin değişmedi, konumu değişti. Bir diff algoritmasının “sonraki 199 satır hâlâ aynı satırlar, sadece bir kaydırılmış” gerçeğini fark edip tek bir ekleme olarak bildirmesi gerekir. LCS’nin size verdiği şey bu tanımadır ve bu yüzden git, GitHub ve her code review aracı bir tane içerir.
1.2 Yan yana ve unified diff
Yan yana, iki sürümü paralel sütunlara yerleştirir ve hücreleri renklendirir: eklenenler için yeşil, silinenler için kırmızı, değişenler için sarı. Unified diff, GNU diff’ten gelen daha eski bir metin biçimidir: tek sütun, - ve + işaretleri, her hunk çevresinde üç satır bağlam. Aynı karşılaştırmanın iki sunumu. Bölüm 4 hangisini ne zaman kullanacağınızı anlatır.
1.3 Text diff’in kullanıldığı yerler
GitHub ve GitLab’da code review. Yerel git diff çıktısı. Slack’e yapıştırılan yamalar. Sözleşme kırmızı kalem incelemesi. Çeviri kontrolü. +/- çıktısıyla başarısız olan CI snapshot testleri. Log zaman çizelgesi incelemesi. İki .env dosyasını karşılaştırma. İki metin parçasının satır satır eşleştirilmesi gereken her durum.
Metin Karşılaştırma aracını açın ve tüm bunları iş başında görmek için iki metin yapıştırın; her karşılaştırma yerel olarak tarayıcınızın içinde çalışır.
2. Text diff’in arkasındaki algoritma (LCS + Myers + Patience)
2.1 Longest Common Subsequence
İki satır dizisi A ve B verildiğinde, Longest Common Subsequence (LCS) ikisinde de aynı sırada (bitişiklik gerekmeden) görünen en uzun satır listesidir. LCS’yi elde ettikten sonra diff doğrudandır: A’da olup LCS’de olmayan satırlar silinir, B’de olup LCS’de olmayan satırlar eklenir, LCS’deki satırlar değişmez.
Klasik LCS, N × M boyutunda bir dinamik programlama tablosu olarak çalışır. (i, j) hücresi, A’nın ilk i satırı ile B’nin ilk j satırının LCS uzunluğunu tutar. Tabloyu soldan sağa, yukarıdan aşağıya doldurun, sonra düzenleme betiğini yeniden oluşturmak için sağ alt hücreden geriye doğru yürüyün. Zaman ve uzay her ikisi de O(N×M): iki bin satırlık dosyalar için yeterli, yüz bin satırlık bir log için yavaş.
2.2 Myers (1986)
Eugene Myers’ın 1986 tarihli “An O(ND) Difference Algorithm and Its Variations” makalesi, sorunu bir düzenleme grafiğinden geçen en kısa yol olarak yeniden çerçeveler: düğümler iki girişteki (i, j) konumları, yatay hareketler silmeler, dikey hareketler eklemeler, çapraz hareketler eşleşmelerdir. En kısa yol, minimum düzenleme betiğidir.
Myers, O((N+M)D) sürede çalışır; burada D, düzenleme betiğinin boyutudur. İki metin benzer olduğunda (diff’ler için olağan durum) D küçüktür ve algoritma esasen doğrusaldır. git diff, GNU diff ve GitHub’ın PR render edicisinde varsayılan budur. Web girişlerinin yüzde doksan dokuzu için doğru cevap odur.
2.3 Patience diff (Bram Cohen, 2005)
Patience diff farklı bir yaklaşım benimser: her girişte tam olarak bir kez görünen satırları (“benzersiz çapa satırları” denir) bulur, bunları eşleştirir ve çapalar arasındaki boşluklarda özyinelemeli olarak çalışır. Matematiği daha dağınıktır (en kötü durum kötü kalır), ancak çıktısı kodda çok daha iyi okunur.
Neden? Myers düzenleme mesafesini en aza indirir; bu matematiksel olarak en uygunudur, fakat en uygun hizalama alakasız süslü parantezleri veya boş satırları kestiğinde görsel olarak berbat olur. Patience, ortak boilerplate üzerinde hizalanmayı reddeder (her dosyada } satırları vardır, her dosyada boş satırlar vardır), böylece fonksiyon sınırları bozulmadan kalır. Bram Cohen bunu Bazaar için icat etti; Git, git diff --patience olarak içerir. Yakından ilişkili Histogram algoritması (git diff --histogram) benzer çıktı kalitesinde biraz daha hızlıdır.
Bir fonksiyonun taşındığı aynı dosyanın iki sürümünü hayal edin. Myers, A fonksiyonunun kapanış süslü parantezini B fonksiyonunun kapanış süslü parantezi ile hizalayabilir ve gövdeleri tamamen farklı olarak raporlayabilir. Patience benzersiz fonksiyon adları üzerine çapalanır ve temiz bir taşıma raporlar. Aynı giriş, çok farklı bir inceleme deneyimi.
2.4 Algoritma karşılaştırması
| Özellik | Myers (varsayılan) | Patience | Histogram |
|---|---|---|---|
| Zaman karmaşıklığı | O((N+M)D) | ~O(N log N) yaygın durum | Patience’a benzer |
| En uygun düzenleme mesafesi | Evet, en kısa betik | Hayır, daha uzun olabilir | Hayır, daha uzun olabilir |
| Kodda doğal okunur | Bazen süslü parantezleri ve boş satırları yanlış hizalar | Mükemmel; benzersiz satırlar üzerine çapalanır | Mükemmel |
| Kullanıldığı yer | git varsayılanı, GNU diff, GitHub UI | git diff --patience, Bazaar | git diff --histogram |
| En uygun olduğu durum | Çoğu girişte hız ve doğruluk | Code review, refactor diff’leri | Patience ile aynı, biraz daha hızlı |
2.5 Bu araç ne yapar
Metin Karşılaştırma, klasik dinamik programlama LCS’sini iki agresif optimizasyonla kullanır: ortak ön ek ve son ek kırpma ve satır içi kelime düzeyinde diff için ikinci bir token düzeyli LCS geçişi. Bir satırı değişmiş iki bin satırlık iki yapılandırmanın diff’i, kırpmadan sonra 1×1 DP tablosuna iner ve bir milisaniyenin altında render edilir. Tipik web girişleri için Myers ile DP arasındaki seçim görünmezdir; her ikisi de tarayıcının sonucu boyamasından daha hızlı biter.
3. Satır içi kelime düzeyinde diff: tek karakterlik değişiklik neden tüm satırı vurguluyor
Bir satırdaki bir tanımlayıcıyı değiştirirsiniz ve tüm satır kırmızı ve yeşil yanar. Hata mı? Hayır, tasarım.
Diff önce satır düzeyinde LCS çalıştırır: “14. satır değiştirildi.” Sonra her değiştirilen çift için token düzeyinde ikinci bir LCS çalıştırır. Token’lar, Unicode kelime sınırlarında bölünerek üretilir; harf ve rakam çalıştırmaları birlikte kalır, boşluk ve noktalama işaretlerinin her biri kendi token’ı olur. İkinci LCS, o satırın içindeki en az token düzeyli düzenleme betiğini verir.
Render edici, gözünüzün bulması için tüm satırı vurgu renginde çizer, sonra parlak arka plan ile yalnızca değişen token’ları boyar. Çevrelerindeki değişmemiş token’lar aynı rengin soluk bir versiyonunu taşır: mevcut ama görsel olarak sessiz. Bakışınız tam olarak düzenlemeye iner.
Örnek 1: tanımlayıcı yeniden adlandırma. function getUser(id) ifadesi function getUser(userId) olur. Tüm satır değiştirilmiş olarak işaretlenir. Satırın içinde yalnızca id (kırmızı üstü çizili) ve userId (parlak yeşil) satır içi vurguyu taşır. Diğer her şey soluk kalır.
Örnek 2: log gecikme değişikliği. POST /api/orders 201 88ms ifadesi POST /api/orders 201 4200ms olur. Satır değiştirilmiştir. Satır içinde yalnızca 88 ve 4200 parlaktır. Yol, yöntem ve durum kodu soluk kalır; bir olay zaman çizelgesi okuyucusunun tam ihtiyacı olan şey.
Çok fazla token değiştiğinde, kelime düzeyinde vurgulama gürültüye dönüşür. Araç, eşleştirilmiş silme + ekleme sunumuna geri döner: orijinal satır silinmiş olarak gösterilir, yeni satır eklenmiş olarak gösterilir, satır içi renklendirme yoktur. Eşik kabaca “token’ların yarısından fazlası farklı” olarak belirlenir.
Özet: satır düzeyli diff hangi satırın değiştiğini söyler; kelime düzeyli diff o satırdaki hangi karakterlerin değişikliği taşıdığını söyler. Aynı girişte her iki görünümü görmek için Metin Karşılaştırma içindeki Örnek düğmesine tıklayın.
4. Yan yana ve unified diff: iki görünüm, tek diff
4.1 Yan yana görünüm
İki sütun: solda orijinal, sağda değiştirilmiş. Eşleşen satırlar yatay olarak hizalanır. Eklenen satırlar yalnızca sağ sütunda yeşil arka planla görünür; silinen satırlar yalnızca sol sütunda kırmızı arka planla görünür; değiştirilen çiftler sarı bir oluk ve satır içi kelime vurgularıyla yan yana durur.
Bir diff’i bir insan okuyacaksa yan yana görünümü kullanın: PR review, öğretim, demolar, teknik olmayan bir paydaşla sözleşme değişikliğini gezdirme. Gözler için olan görünüm budur.
Dezavantajı: taşınmaz. Yan yana bir render’ı Slack’e yapıştırıp birinin uygulamasını sağlayamazsınız. patch’a pipe edemezsiniz. Paylaşım ve uygulama için unified gerekir.
4.2 Unified diff biçimi
Unified diff, GNU diff tarafından tanımlanmış ve POSIX’te standartlaştırılmış elli yıllık bir düz metin biçimidir. Tam bir örnek:
--- original
+++ modified
@@ -1,3 +1,4 @@
1. The service is provided as-is.
2. Either party may terminate with 30 days notice.
+2a. Termination notice must be in writing.
3. Disputes are resolved in California courts.
İlk iki satır kaynak dosyaları adlandırır. @@ -L,C +L,C @@ satırı bir hunk başlığıdır: -L,C, orijinalin L. satırından başlayarak C satırın dahil olduğu anlamına gelir; +L,C aynı şeyi değiştirilmiş sürüm için söyler. Hunk içinde boşlukla başlayan satırlar bağlamdır (değişmemiş), - silinmiştir, + eklenmiştir.
Her değişikliğin altında ve üstünde üç satır bağlam GNU varsayılanıdır. Çoğu araç bunu -U n ile değiştirmenize izin verir: bağlamsız için diff -U0, on satırlık bağlam için diff -U10. Hunk başlığı seçtiğiniz değeri izler.
Metin Karşılaştırma içinde, görünümleri değiştirmek için Unified sekmesine tıklayın ya da yamayı panonuza koymak için Copy unified diff düğmesine tıklayın.
4.3 Unified diff’in taşınabilir olduğu yerler
Unified diff yolculuk eder. Metinsel değişikliğin evrensel para birimidir.
| Hedef | Unified diff’i kabul eder mi? | Nasıl |
|---|---|---|
GNU patch | Evet | patch -p1 < diff.patch |
git apply | Evet | git apply diff.patch |
| GitHub PR review yorumu | Evet (bir ```diff bloğu içinde) | Renkle render edilir |
| GitLab MR yorumu | Evet | Aynı fenced blok |
| Bitbucket / Azure DevOps PR | Evet | Aynı fenced blok |
| Slack / Discord yapıştırma | Kısmen | Bir code block içinde metin olarak render edilir, renk yok |
| VS Code “Open Patch” | Evet | Source Control üzerinden yama uygula |
| Jira / Linear issue gövdesi | Kısmen | Code block içinde çalışır, uygula düğmesi yok |
Aynı dokuz satırlık ---/+++/@@ metni patch üzerinde, git apply üzerinde uygulanır, üç PR platformunda render edilir ve Slack yapıştırmasında hayatta kalır. Bu, herhangi bir diff biçiminin sahip olduğu en geniş erişim sahasıdır.
4.4 Hangisini ne zaman seçmeli
İnceleme için yan yana, paylaşım ve uygulama için unified. Diff’i kendiniz okuyorsanız sütunlar daha hızlıdır. Aşağı akışta herhangi biri veya herhangi bir şey bunu tüketmesi gerekiyorsa (bir gözden geçirici, bir araç, bir patch komutu) unified biçimini kopyalayın.
5. Yoksayma seçenekleri: boşluk, büyük/küçük harf, boş satırlar, satır sonları
“Her şey değişmiş gibi görünüyor” şikâyetlerinin çoğu gürültüdür. Dört düğme bunların %95’ini düzeltir.
- Büyük/küçük harfi yoksay,
A’yıa’ya eşler.git diff -iile eşdeğerdir. Ortam değişkeni karşılaştırmaları, SQL anahtar kelime stil denetimleri, kuralın bağırgan büyük harfler ile sessiz büyük harfler olduğu, ama anlamın özdeş olduğu her yerde kullanın. - Tüm boşlukları yoksay, karşılaştırmadan önce her boşluk, tab ve satır sonunu birleştirir.
git diff -wile eşdeğerdir. Tab ↔ boşluk yeniden biçimlendirme, girinti yeniden yazımları ve satır sayılarını yok eden “Prettier’a geçtik” diff’lerinin ilacıdır. Bu değişikliklerde tüm boşlukları yoksayan bir diff tipik olarak 87 değişiklikten 4’e iner. - Sondaki boşlukları ve tab’leri yoksay, yalnızca satır sonu boşluklarını çıkarır.
git diff -bile eşdeğerdir. Windows ve Unix makineler arasında kopyalama sonrası CRLF gürültüsünün ilacıdır: sondaki\rkarakterleri filtrelenir ve gerçek içerik hizalanır. - Boş satırları yoksay, diff’lemeden önce boş satırları düşürür. Düzyazı diff’lerinde “bir paragraf arası ekledim ve şimdi 12. paragraf tamamen farklı görünüyor” sorununun ilacıdır.
“87 değişiklik” raporlayan 200 satırlık bir yapılandırma, Tüm boşlukları yoksay sonrası genellikle “4 değişiklik”e iner. Her satırı işaretleyen bir Windows-Unix kopyası, Sondaki boşlukları yoksay ile sıfıra iner. Her düğme bağımsızdır ve oturumlar arasında kalıcıdır.
CRLF ile LF. Windows satır sonları \r\n’dir; Unix \n’dir; klasik Mac \r’dir. Normalleştirmeyen bir Unix editöründe bir Windows dosyasını açın ve sondaki \r’yi tutarsınız. Her satır “içerik eşleşir ama sonda bir \r vardır” olarak diff’lenir. Sondaki boşlukları yoksay, gerçek değişiklikleri kaybetmeden bunu susturur.
Dikkat. Yoksayma seçenekleri iki ucu keskin bıçaktır. Büyük/küçük harfi yoksay’ı açın ve LOG.error ifadesini log.Error yapan bir refactor özdeş görünür. Tüm boşlukları yoksay’ı açın ve bir Python girinti hatası görünmez olur. Sorduğunuz soru için düğmeleri seçin, işiniz bittiğinde kapatın.
6. Text diff ile JSON diff ile Git diff: karar matrisi
Text diff, yapıyı anlamadan satır ve kelime eşleştirmesidir. Düzyazı için tam olarak istediğiniz şey, JSON için tam olarak istemediğiniz şeydir.
6.1 Karar matrisi
| Giriş türü | Text diff | JSON diff | Git diff |
|---|---|---|---|
| Düzyazı / Markdown / sözleşme | En iyi | Yanlış araç | Kısmen (yalnızca izlenen dosyalarda çalışır) |
| Kod parçacığı (tek dosya yapıştırma) | En iyi | Yanlış araç | Kısmen (bir depo gerekir) |
| Depodaki kod (çoklu dosya) | Kısmen | Yanlış araç | En iyi |
| API JSON yanıtı | Yanlış araç (anahtar sırasında yanlış pozitifler) | En iyi | Yanlış araç |
| YAML / TOML yapılandırma | Kısmen (anahtar sırasında yanlış pozitifler) | En iyi (dönüştürmeden sonra) | Kısmen |
| CSV satır satır | Kısmen | Yanlış araç | Yanlış araç |
| Log / heredoc | En iyi | Yanlış araç | Yanlış araç |
| İkili dosya | Yanlış araç | Yanlış araç | git diff --binary |
6.2 Text diff’in yanlış araç olduğu durumlar
Üç klasik hata.
Anahtarları yeniden sıralanmış JSON. {"a":1,"b":2} ve {"b":2,"a":1} aynı JSON belgesidir. Bir text diff her satırı değişmiş olarak raporlar, çünkü bunlar gerçekten farklı satırlardır. JSON Diff kullanın; JSON anahtarlarının sırasız olduğunu anlar.
Yeniden biçimlendirilmiş YAML yapılandırmaları. Bir değeri değiştirin, dosyayı bir biçimlendiriciden geçirin ve girinti, anahtar sırası ve tırnak kullanımı hepsi kayar. Text diff tam bir yeniden yazma raporlar. Her iki dosyayı önce JSON’a dönüştürün, sonra JSON Diff ile karşılaştırın.
Yeniden adlandırmalı çoklu dosya refactor’ları. Git yeniden adlandırmaları izler; text diff izlemez. İki ağacı dosyaları tek bir blob’a birleştirerek karşılaştırırsanız, her dosyalar arası taşıma silinmiş + eklenmiş olarak görünür. Bunun yerine git diff (veya git diff --find-renames=80%) kullanın.
6.3 Text diff’in tam olarak doğru olduğu durumlar
Düzyazı. Her yerden yapıştırılmış kod parçacıkları. Sözleşme kırmızı kalem incelemeleri. Log dilimleri. Doğal dil cümlelerini eşleştirdiğiniz çeviri incelemeleri. Kabuklar dosyayı yukarıdan aşağıya okuduğu için sıranın önemli olduğu .env dosyaları. Satırların kendilerinin anlam taşıdığı her şey.
JSON diff’lerinden gürültü filtreleme (zaman damgaları, request ID’leri, otomatik üretilen UUID’ler) konusunda derin bir inceleme için JSON Diff’te Zaman Damgaları ve ID’ler Nasıl Yoksayılır yazısını okuyun.
7. Gerçek dünyadan altı senaryo (kopyala-yapıştır girdilerle)
7.1 Code review parçacığı: fonksiyon yeniden adlandırma
Bir PR’yi inceliyorsunuz. Yazar id’yi userId olarak yeniden adlandırdı ve bir guard clause ekledi. Her iki sürümü yapıştırın:
// Original
function getUser(id) {
const u = db.users.find(x => x.id === id);
return u;
}
// Modified
function getUser(userId) {
if (!userId) return null;
const u = db.users.find(x => x.id === userId);
return u;
}
Diff, üç değiştirilmiş satır artı bir eklenmiş satır gösterir. Satır içi kelime vurgulama her id → userId token’ını işaretler; yeni guard clause yeşil arka planla görünür. Yoksayma seçenekleri kapalı. Metin Karşılaştırma içinde deneyin ve unified çıktıyı bir review yorumu olarak bırakmak için kopyalayın.
7.2 Sözleşme veya politika kırmızı kalem: bir madde ekleme
Elli paragraflık sözleşme, bir madde eklenmiş. Solda dünkü sürümü, sağda bugünkü sürümü yapıştırın:
1. The service is provided as-is.
2. Either party may terminate with 30 days notice.
3. Disputes are resolved in California courts.
1. The service is provided as-is.
2. Either party may terminate with 30 days notice.
2a. Termination notice must be in writing.
3. Disputes are resolved in California courts.
Diff kırk dokuz değişmemiş satırı ve bir eklenmiş satırı (+2a. Termination notice must be in writing.) render eder. Yasal inceleme izi olarak unified diff’i dışa aktarın.
7.3 Log zaman çizelgesi incelemesi
Bir gecikme regresyonundan şüpheleniyorsunuz. Olaydan önceki ve sırasındaki bir erişim log dilimi alın:
GET /api/users 200 14ms
POST /api/orders 201 88ms
GET /api/orders/42 200 21ms
GET /api/users 200 14ms
POST /api/orders 201 4200ms
GET /api/orders/42 500 21ms
Satır içi vurgu 88 → 4200 (50× gecikme sıçraması) ve 200 → 500 (bir order detail endpoint’inin başarısız olmaya başlaması) değişimlerini ortaya koyar. Daha zengin log işleri için (alanları çekme, endpoint’e göre gruplama, yüzdelikleri hesaplama) log’larınız JSON ise diff’i jq Hile Sayfası ile eşleştirin.
7.4 Çeviri incelemesi: placeholder’ları koruma
Yeni bir çeviri ajansı tuttunuz ve yeni metnin eskisiyle yapısal olarak eşleştiğini doğrulamak istiyorsunuz. Solda eski çeviriyi, sağda yenisini yapıştırın. Sondaki boşlukları / tab’leri yoksay’ı açın çünkü çevirmenler düzenli olarak karakter dizilerinin sonuna fazladan bir boşluk ekler.
Diff her {username}, {count} ve %s placeholder’ının yerinde kaldığını doğrular; yalnızca doğal dil metni değişir. Eksik bir placeholder satır içi diff’te silinmiş bir token olarak görünür, siz yayımlamadan yakalanır. Placeholder biçimlerinin kendisini karşılaştırmanız gerekiyorsa Regex Hile Sayfası \{\w+\} ve arkadaşlarını kapsar. Metin Karşılaştırma içinde deneyin.
7.5 Yapılandırma veya .env denetimi: production ile staging
İki .env dosyasını karşılaştırın. Paragraf tarzı gruplamanın bölümleri yanlış hizalamaması için Boş satırları yoksay’ı açın. Diff size hangi anahtarların değer farkı taşıdığını, hangi anahtarların bir ortamda var olup diğerinde olmadığını ve yorumların nerede senkrondan çıktığını gösterir. “Staging’de çalışıyor ama prod’da değil” hata ayıklama oturumunu önleyen beş dakika.
7.6 Düzyazı veya taslak revizyonu
Editörünüz size bir taslak geri verdi. Solda orijinalinizi, sağda düzenlenmiş sürümü yapıştırın. Satır içi kelime diff size hangi cümlelerin yeniden yazıldığını, hangilerinin dokunulmadığını ve hangi paragrafların eklendiğini tam olarak gösterir. Değişiklikleri tek tek kabul edin ya da reddedin: Track Changes özelliği yok, Word dosyası yok, tescilli biçim yok.
8. Yaygın tuzaklar ve bunları belirti olarak okumak
Algoritma davranışı kullanıcı acılarının çoğunu açıklar. Beş yaygın şikâyet ve gerçekte ne anlama geldikleri.
Tuzak 1: “Windows’tan Unix’e kopyalama sonrası her satır kırmızı.” Belirti: içerik özdeş görünmesine rağmen diff’teki her satır değişmiş olarak görünür. Sebep: CRLF satır sonlarından kaynaklanan sondaki \r karakterleri. Çözüm: Sondaki boşlukları / tab’leri yoksay’ı açın. Diff gerçek değişikliklere düşecek.
Tuzak 2: “JSON yapıştırdım ve satırların %100’ü farklı.” Belirti: eşdeğer olması gereken iki JSON nesnesi tamamen değişmiş olarak görünüyor. Sebep: anahtar yeniden sıralama. Text diff satır sırasını anlamlı olarak ele alır; JSON almaz. Çözüm: herhangi bir JSON girişi için JSON Diff kullanın.
Tuzak 3: “Tab ↔ boşluk yeniden biçimlendirmesi diff’i havaya uçurdu.” Belirti: 87 değişiklik, hepsi girinti. Sebep: biçimlendiricin her satırın öndeki boşluğunu değiştirdi. Çözüm: Tüm boşlukları yoksay gürültüyü birleştirir ve gerçek anlamsal değişiklikleri öne taşır.
Tuzak 4: “Diff özdeş diyor ama cmp aynı fikirde değil.” Belirti: diff hiç fark olmadığını raporlar ama byte düzeyli bir karşılaştırma dosyaların farklı olduğunu söyler. Sebep: önceki bir oturumdan kalmış açık bir yoksayma seçeneği gerçek değişiklikleri maskeliyor. Çözüm: Yoksayma seçenekleri panelini açın ve her düğmeyi kapatın, sonra yeniden diff’leyin.
Tuzak 5: “Tek kısa bir düzenleme silme + ekleme olarak görünüyor.” Belirti: küçük bir değişiklik satır içi vurgu yerine ayrı bir silinmiş satır ve ayrı bir eklenmiş satır olarak görünür. Sebep: değişen token’ların oranı satır içi eşiği aştı ve render edici eşleştirilmiş satır sunumuna geri döndü. Bu tasarım, hata değil. Patch araçlarının beklediği klasik -/+ çiftini görmek için Unified görünümüne geçin.
9. Gizlilik, performans ve komut satırına ne zaman uzanmalı
Metin Karşılaştırma içindeki her karşılaştırma tarayıcınızın içindeki JavaScript’te çalışır. Yükleme yok, geçici dosya yok, sunucu log’u yok, yapıştırdığınız metin üzerinde analytics yok. Tescilli kod, dahili sözleşmeler, özel log’lar için güvenli; üçüncü taraf bir sunucuya yapıştırmak istemeyeceğiniz her şey için uygundur.
Pratik sınırlar: her taraf için yaklaşık 5.000 satır veya 1 MB. Canlı diff, birleşik 200 KB’nin üzerinde devre dışı kalır ve yazmanın sayfayı bloke etmemesi için manuel bir Diff düğmesine geçer. 5.000 satırın üzerinde girdi kesilir ve bir uyarı görünür. Sınırlar var çünkü diff ana iş parçacığında çalışıyor (web worker yok) ve küçük girdilerde bir worker devri artı serileştirme diff’in kendisinden daha fazlasına mal olur.
Girdiniz tarayıcıyı aştığında komut satırına geçin:
# Unified diff between two files
diff -u a.txt b.txt
# Same, but using git's diff engine (Patience, Histogram, color)
git diff --no-index a.txt b.txt
git diff --no-index --patience a.txt b.txt
# Streaming diff viewer for huge files (Rust, side-by-side, syntax-aware)
delta a.txt b.txt
Çok megabaytlı log’lar, ikili dosyalar, çoklu dosya depo diff’leri, delta gibi sözdizimi-bilinçli renklendirme istediğiniz her şey ya da diff çıktısını başka bir araca pipe etmeniz gereken her yer için komut satırına geçin.
10. Unicode, CJK ve RTL: uluslararası text diff notları
Tokenleştirici, Unicode kelime sınırlarında üç kategori kullanarak böler: kelime çalıştırmaları (\p{L} harfler ve \p{N} rakamlar), kelime olmayan noktalama ve boşluk. Her kategori kendi token’larını üretir, böylece hello, world! beş token olur: hello, ,, , world, !.
CJK içeriği (Çince, Japonca, Korece) için her ideograf veya kana kendi token’ıdır. Bir Çince cümlede bir karakteri değiştirin ve satırın geri kalanı soluk kalırken yalnızca o karakter satır içi vurguyu taşır. Paragraf düzeyli yapı hâlâ satır temelli, bu nedenle bir satır sonu ekleyen bir cümle yeniden yazımı, token düzeyli değil, satır düzeyli bir düzenleme olarak görünür.
RTL diller (Arapça, İbranice) için diff mantıksal CSS yönleri kullanır (ml-, mr- yerine ms-, me-). RTL yerellerde oluk ve satır sütunları doğal olarak çevrilir; her diff hücresinin içinde metin yönü içeriği takip eder, böylece Arapça karakter dizileri sağdan sola render edilirken + ve - işaretleri başlangıç oluğuna hizalı kalır.
Satır sonu normalleştirme \r\n (Windows), \n (Unix) ve çıplak \r’yi (eski Mac OS 9’a kadar) tanır. Üçü de ayrı satırlar olarak bölünür, bu nedenle bir platformdan diğerine dönüştürülen bir dosya tek bir mega satıra çökmez.
11. SSS
Çevrim içi bir text diff nasıl çalışır?
Bir text diff her iki girişi satırlara böler, en küçük ekleme ve silme kümesini bulmak için bir Longest Common Subsequence algoritması çalıştırır (tipik olarak Myers’ın O((N+M)D)‘si), sonra eklenen (yeşil), silinen (kırmızı) ve değişmemiş (gri) satırları vurgular. İkinci bir token düzeyli LCS, her değiştirilen satırdaki değişen kelimeleri işaretler. Metin Karşılaştırma tüm karşılaştırmayı tarayıcınızda yerel olarak çalıştırır.
Text diff ile JSON diff arasındaki fark nedir?
Text diff satır satır karşılaştırır; düzyazı, kod, log ve sözleşmeler için idealdir. JSON Diff, JSON’un veri modelini anlar: anahtar sırası önemsizdir, türler katıdır (1 ≠ "1"), diziler anahtara göre eşleştirilebilir. JSON’u bir text diff’e yapıştırın ve anahtar yeniden sıralamaları veya boşluklar JSON Diff’in yoksayacağı değişiklikler olarak öne çıkar. Yapılandırılmamış içerik için text diff, API yanıtları ve yapılandırmalar için JSON Diff kullanın.
Yalnızca bir kelime düzenlediğimde diff neden tüm satırı değişmiş gösteriyor?
Göstermez: satır vurgulanır çünkü üzerinde bir şey değişti, ama vurgunun içinde yalnızca değişen token’lar parlak arka planı taşır (eklenen için yeşil, silinen için kırmızı üstü çizili). Bu, satır içi kelime düzeyinde diff’tir: satır bağlamı okunabilir kalır, bakışınız tam olarak düzenlemeye iner. Kelime düzeyinde vurgulamanın yararlı olamayacağı kadar bir satır değiştiğinde, yapının temiz kalması için diff ayrı bir silme + ekleme çiftine geri döner.
Diff’te boşluğu, büyük/küçük harfi veya boş satırları nasıl yoksayarım?
Yoksayma seçenekleri panelini açıp kapatın. Büyük/küçük harfi yoksay A ile a’yı eşit kılar. Tüm boşlukları yoksay her boşluk, tab ve satır sonunu birleştirir; git diff -w ile eşdeğerdir. Sondaki boşlukları ve tab’leri yoksay git diff -b’yi yansıtır ve CRLF gürültüsünü susturur. Boş satırları yoksay boş satırları düşürür, böylece paragraf yeniden aralandırma diff’i yanlış hizalamaktan vazgeçer. Her seçenek bağımsızdır ve oturumlar arasında kalıcıdır.
Unified diff biçimi nedir?
Unified diff, 1980’lerin sonlarında GNU diff tarafından tanıtılan ve git, GitHub, GitLab ve Unix patch komutu tarafından kullanılan ---/+++/@@ -L,C +L,C @@ metin biçimidir. Her hunk, değişiklik etrafında üç bağlam satırı gösterir; silinen için -, eklenen için +. Unified çıktıyı bir PR yorumuna kopyalayın, git apply içine yapıştırın ya da patch -p1 < diff.patch çalıştırın; temiz uygulanır.
Myers ile Patience: code review için hangi diff algoritması daha iyi?
Myers, git diff ve GNU diff’in varsayılanıdır: hızlı ve matematiksel olarak minimal, ama bazen alakasız boş satırları veya kapanış süslü parantezlerini hizalar ve “tuhaf okunan” diff’ler üretir. Patience (Bram Cohen, 2005) her girişte tam olarak bir kez görünen satırlar üzerine çapalanır ve çapalar arasında özyinelemeli olarak çalışır, böylece fonksiyon sınırları korunur. Refactor’ları incelerken git diff --patience (ya da benzer sonuçlar için biraz daha hızlı --histogram) kullanın.
Yapıştırdığım metin bir sunucuya gönderiliyor mu?
Hayır. Metin Karşılaştırma içindeki her karşılaştırma tarayıcınızın içindeki JavaScript’te yerel olarak çalışır. Metniniz asla yüklenmez, log’lanmaz, diske kaydedilmez veya herhangi bir üçüncü tarafa gönderilmez. Yalnızca UI tercihleriniz (görünüm modu ve yoksayma seçeneği düğmeleri), sayfa bir sonraki ziyarette bunları hatırlasın diye localStorage’a kaydedilir; metin asla. DevTools → Network ile doğrulayın: Diff’e tıkladığınızda sıfır istek tetiklenir.
İki girdi ne kadar büyük olabilir?
Pratik sınır, her taraf için yaklaşık 5.000 satır veya 1 MB’dir. Canlı diff, birleşik 200 KB’nin üzerinde devre dışı kalır ve manuel bir Diff düğmesine geçer. 5.000 satırın üzerinde girdi bir uyarıyla kesilir. Çok megabaytlı dosyalar için diff -u a.txt b.txt, git diff --no-index a.txt b.txt ya da delta’ya geçin; bunlar akış yapar ve gigabaytları işler.