[{"data":1,"prerenderedAt":480},["ShallowReactive",2],{"guide-diff-algorithms-explained":3},{"id":4,"title":5,"body":6,"date":471,"description":472,"extension":473,"meta":474,"navigation":475,"path":476,"readingTime":144,"seo":477,"stem":478,"__hash__":479},"guides\u002Fguides\u002Fdiff-algorithms-explained.md","Diff Algorithms Explained: Myers, Patience, and Histogram",{"type":7,"value":8,"toc":449},"minimark",[9,14,23,26,29,33,40,45,48,51,73,77,88,92,100,154,162,166,177,180,199,202,213,216,224,230,234,245,248,262,265,276,279,287,291,361,364,375,379,405,408,412,433,437,445],[10,11,13],"h2",{"id":12},"the-problem-behind-every-diff","The Problem Behind Every Diff",[15,16,17,18,22],"p",{},"Every diff tool solves the same mathematical problem: finding the ",[19,20,21],"strong",{},"Longest Common Subsequence (LCS)"," between two sequences of lines. The LCS is the longest set of lines that appear in both texts in the same order — though not necessarily contiguously.",[15,24,25],{},"Once you know the LCS, everything else is a deletion (lines in the original but not in the LCS) or an addition (lines in the new text but not in the LCS).",[15,27,28],{},"The challenge? The LCS problem is computationally expensive. A naive approach has exponential time complexity. Different algorithms trade accuracy, speed, and readability in different ways.",[10,30,32],{"id":31},"myers-diff-algorithm","Myers Diff Algorithm",[15,34,35,36,39],{},"The Myers algorithm is the default in Git and most command-line diff tools. Published by Eugene Myers in 1986, it finds the ",[19,37,38],{},"shortest edit script"," — the smallest set of insertions and deletions that transforms the original text into the new text.",[41,42,44],"h3",{"id":43},"how-it-works","How It Works",[15,46,47],{},"Myers treats the comparison as a graph search. Each point represents a position in both texts. The algorithm searches diagonally (matching lines) and horizontally or vertically (edits) to find the shortest path from start to finish.",[15,49,50],{},"Key properties:",[52,53,54,61,67],"ul",{},[55,56,57,60],"li",{},[19,58,59],{},"O(ND) time complexity"," — where N is the total text length and D is the number of differences",[55,62,63,66],{},[19,64,65],{},"O(N²) worst case"," — when texts are completely different",[55,68,69,72],{},[19,70,71],{},"Linear in matching regions"," — when texts share long common sections, it runs nearly in O(N)",[41,74,76],{"id":75},"strengths","Strengths",[52,78,79,82,85],{},[55,80,81],{},"Produces the minimal edit script — no redundant insertions or deletions",[55,83,84],{},"Fast when differences are small relative to file size (the common case)",[55,86,87],{},"Well-tested and battle-proven in Git",[41,89,91],{"id":90},"weaknesses","Weaknesses",[52,93,94,97],{},[55,95,96],{},"Can produce awkward output when moved blocks exist — it may break a moved function into scattered deletions and insertions",[55,98,99],{},"Does not recognize renames or moves natively",[101,102,107],"pre",{"className":103,"code":104,"language":105,"meta":106,"style":106},"language-diff shiki shiki-themes github-light github-dark","- function validate(input) {\n-   return input.length > 0;\n- }\n  \u002F\u002F ... 50 lines of unchanged code ...\n+ function validate(input) {\n+   return input.trim().length > 0;\n+ }\n","diff","",[108,109,110,118,124,130,136,142,148],"code",{"__ignoreMap":106},[111,112,115],"span",{"class":113,"line":114},"line",1,[111,116,117],{},"- function validate(input) {\n",[111,119,121],{"class":113,"line":120},2,[111,122,123],{},"-   return input.length > 0;\n",[111,125,127],{"class":113,"line":126},3,[111,128,129],{},"- }\n",[111,131,133],{"class":113,"line":132},4,[111,134,135],{},"  \u002F\u002F ... 50 lines of unchanged code ...\n",[111,137,139],{"class":113,"line":138},5,[111,140,141],{},"+ function validate(input) {\n",[111,143,145],{"class":113,"line":144},6,[111,146,147],{},"+   return input.trim().length > 0;\n",[111,149,151],{"class":113,"line":150},7,[111,152,153],{},"+ }\n",[15,155,156,157,161],{},"In this case, Myers correctly detects the change, but if the entire function were ",[158,159,160],"em",{},"moved"," to a different location, it would show as a deletion at the old spot and an addition at the new one.",[10,163,165],{"id":164},"patience-diff-algorithm","Patience Diff Algorithm",[15,167,168,169,172,173,176],{},"Patience diff was created by Bram Cohen (also the creator of BitTorrent) and adopted by Git as an alternative strategy (",[108,170,171],{},"git diff --patience","). It focuses on producing ",[19,174,175],{},"more readable output for code",".",[41,178,44],{"id":179},"how-it-works-1",[181,182,183,190,193,196],"ol",{},[55,184,185,186,189],{},"Find all lines that appear ",[19,187,188],{},"exactly once"," in both texts — these are \"unique\" lines",[55,191,192],{},"Compute the LCS of these unique lines using a patience-sorting approach",[55,194,195],{},"Use the unique-line LCS as anchor points",[55,197,198],{},"Run Myers diff on the segments between anchors",[41,200,76],{"id":201},"strengths-1",[52,203,204,207,210],{},[55,205,206],{},"Better at preserving the structure of moved code blocks",[55,208,209],{},"Function signatures, class declarations, and closing braces act as natural anchors",[55,211,212],{},"Output aligns with how developers mentally parse code",[41,214,91],{"id":215},"weaknesses-1",[52,217,218,221],{},[55,219,220],{},"Slower than Myers when there are few unique lines (degenerate cases)",[55,222,223],{},"Still does not detect moves explicitly — it just avoids splitting them",[15,225,226,229],{},[19,227,228],{},"Example",": When a developer moves an entire method from the top of a file to the bottom, patience diff keeps the method intact instead of showing it as scattered line-level changes.",[10,231,233],{"id":232},"histogram-diff-algorithm","Histogram Diff Algorithm",[15,235,236,237,240,241,244],{},"Histogram diff is the default in JGit (the Java implementation of Git) and is available in Git via ",[108,238,239],{},"git diff --histogram",". It extends patience diff with a focus on ",[19,242,243],{},"low-occurrence lines"," rather than strictly unique lines.",[41,246,44],{"id":247},"how-it-works-2",[181,249,250,256,259],{},[55,251,252,253],{},"For each segment between anchors, find the longest matching subsequence using lines with the ",[19,254,255],{},"lowest occurrence count",[55,257,258],{},"If a line appears 2 times in both texts,Histogram still considers it — patience would skip it",[55,260,261],{},"Recurse on remaining segments until no more matches exist",[41,263,76],{"id":264},"strengths-2",[52,266,267,270,273],{},[55,268,269],{},"More robust than patience diff — it handles files with repeated patterns (like boilerplate code) better",[55,271,272],{},"Often produces the most readable output for real-world codebases",[55,274,275],{},"Falls back gracefully — when no low-occurrence lines exist, it behaves like Myers",[41,277,91],{"id":278},"weaknesses-2",[52,280,281,284],{},[55,282,283],{},"Slightly slower than patience due to the additional occurrence-counting pass",[55,285,286],{},"Implementation complexity is higher",[10,288,290],{"id":289},"performance-comparison","Performance Comparison",[292,293,294,313],"table",{},[295,296,297],"thead",{},[298,299,300,304,307,310],"tr",{},[301,302,303],"th",{},"Algorithm",[301,305,306],{},"Time Complexity",[301,308,309],{},"Best For",[301,311,312],{},"Default In",[314,315,316,331,346],"tbody",{},[298,317,318,322,325,328],{},[319,320,321],"td",{},"Myers",[319,323,324],{},"O(ND)",[319,326,327],{},"Small diffs, general use",[319,329,330],{},"Git",[298,332,333,336,339,342],{},[319,334,335],{},"Patience",[319,337,338],{},"O(N log N) + O(ND)",[319,340,341],{},"Code with moved blocks",[319,343,344],{},[108,345,171],{},[298,347,348,351,353,356],{},[319,349,350],{},"Histogram",[319,352,338],{},[319,354,355],{},"Real-world codebases",[319,357,358,359],{},"JGit, ",[108,360,239],{},[15,362,363],{},"In practice, the differences are subtle for small files. They become noticeable on files with:",[52,365,366,369,372],{},[55,367,368],{},"Hundreds of lines changed",[55,370,371],{},"Moved or reordered functions",[55,373,374],{},"Repeated boilerplate patterns",[10,376,378],{"id":377},"which-algorithm-should-you-use","Which Algorithm Should You Use?",[52,380,381,387,393,399],{},[55,382,383,386],{},[19,384,385],{},"General text comparison",": Myers — fast and minimal",[55,388,389,392],{},[19,390,391],{},"Code review with moved blocks",": Patience — cleaner alignment of functions",[55,394,395,398],{},[19,396,397],{},"Large files with repeated patterns",": Histogram — most robust output",[55,400,401,404],{},[19,402,403],{},"Performance-critical pipelines",": Myers — predictable O(ND) behavior",[15,406,407],{},"Most online diff tools hide the algorithm choice and use Myers or a hybrid approach. The best tool is the one that gives you output you can read and trust.",[10,409,411],{"id":410},"related-guides","Related Guides",[52,413,414,421,427],{},[55,415,416],{},[417,418,420],"a",{"href":419},"\u002Fguides\u002Ftext-diff-guide","Text Comparison Guide",[55,422,423],{},[417,424,426],{"href":425},"\u002Fguides\u002Fcode-review-diff-tips","Code Review Diff Tips",[55,428,429],{},[417,430,432],{"href":431},"\u002Fguides\u002Fregex-performance-tips","Regex Performance Tips",[10,434,436],{"id":435},"try-it-yourself","Try It Yourself",[15,438,439,440,444],{},"Use our free ",[417,441,443],{"href":442},"\u002Ftools\u002Fdiff-checker","Diff Checker"," to compare texts instantly. Paste two versions, see every addition and deletion highlighted, and choose the view that fits your workflow — no command line needed.",[446,447,448],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":106,"searchDepth":120,"depth":120,"links":450},[451,452,457,462,467,468,469,470],{"id":12,"depth":120,"text":13},{"id":31,"depth":120,"text":32,"children":453},[454,455,456],{"id":43,"depth":126,"text":44},{"id":75,"depth":126,"text":76},{"id":90,"depth":126,"text":91},{"id":164,"depth":120,"text":165,"children":458},[459,460,461],{"id":179,"depth":126,"text":44},{"id":201,"depth":126,"text":76},{"id":215,"depth":126,"text":91},{"id":232,"depth":120,"text":233,"children":463},[464,465,466],{"id":247,"depth":126,"text":44},{"id":264,"depth":126,"text":76},{"id":278,"depth":126,"text":91},{"id":289,"depth":120,"text":290},{"id":377,"depth":120,"text":378},{"id":410,"depth":120,"text":411},{"id":435,"depth":120,"text":436},"2026-05-27","Understand the algorithms behind diff tools. Compare Myers, patience, and histogram diff algorithms and their trade-offs.","md",{"immutable":475},true,"\u002Fguides\u002Fdiff-algorithms-explained",{"title":5,"description":472},"guides\u002Fdiff-algorithms-explained","sJf1NflxU6_vumfIRhhhTqAN5O1Tqdy7_y6CCm05JJQ",1780401324917]