[{"data":1,"prerenderedAt":683},["ShallowReactive",2],{"guide-unified-diff-format-explained":3},{"id":4,"title":5,"body":6,"date":675,"description":676,"extension":677,"meta":678,"navigation":107,"path":679,"readingTime":80,"seo":680,"stem":681,"__hash__":682},"guides\u002Fguides\u002Funified-diff-format-explained.md","Unified Diff Format Explained",{"type":7,"value":8,"toc":660},"minimark",[9,14,27,30,34,37,115,118,123,136,160,164,172,179,205,209,257,266,270,276,364,367,371,374,420,427,448,452,455,496,499,503,506,515,522,556,560,598,602,644,648,656],[10,11,13],"h2",{"id":12},"what-is-unified-diff","What Is Unified Diff?",[15,16,17,18,22,23,26],"p",{},"Unified diff is the standard format for representing differences between two versions of a text file. Created for the ",[19,20,21],"code",{},"diff -u"," command in Unix, it became the universal format adopted by Git, Mercurial, Subversion, and every major patch tool. If you have ever run ",[19,24,25],{},"git diff",", you have already read unified diff output.",[15,28,29],{},"The format is designed to be both human-readable and machine-parseable — you can see what changed at a glance, and tools can apply the same diff as a patch to transform one file into another.",[10,31,33],{"id":32},"anatomy-of-a-unified-diff","Anatomy of a Unified Diff",[15,35,36],{},"Here is a typical unified diff:",[38,39,44],"pre",{"className":40,"code":41,"language":42,"meta":43,"style":43},"language-diff shiki shiki-themes github-light github-dark","--- a\u002Fsrc\u002Futils\u002Fformat.js\n+++ b\u002Fsrc\u002Futils\u002Fformat.js\n@@ -12,7 +12,7 @@ function formatDate(date) {\n   const year = date.getFullYear();\n   const month = date.getMonth() + 1;\n   const day = date.getDate();\n-  return `${year}-${month}-${day}`;\n+  return `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`;\n }\n\n function parseDate(str) {\n","diff","",[19,45,46,54,60,66,72,78,84,90,96,102,109],{"__ignoreMap":43},[47,48,51],"span",{"class":49,"line":50},"line",1,[47,52,53],{},"--- a\u002Fsrc\u002Futils\u002Fformat.js\n",[47,55,57],{"class":49,"line":56},2,[47,58,59],{},"+++ b\u002Fsrc\u002Futils\u002Fformat.js\n",[47,61,63],{"class":49,"line":62},3,[47,64,65],{},"@@ -12,7 +12,7 @@ function formatDate(date) {\n",[47,67,69],{"class":49,"line":68},4,[47,70,71],{},"   const year = date.getFullYear();\n",[47,73,75],{"class":49,"line":74},5,[47,76,77],{},"   const month = date.getMonth() + 1;\n",[47,79,81],{"class":49,"line":80},6,[47,82,83],{},"   const day = date.getDate();\n",[47,85,87],{"class":49,"line":86},7,[47,88,89],{},"-  return `${year}-${month}-${day}`;\n",[47,91,93],{"class":49,"line":92},8,[47,94,95],{},"+  return `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`;\n",[47,97,99],{"class":49,"line":98},9,[47,100,101],{}," }\n",[47,103,105],{"class":49,"line":104},10,[47,106,108],{"emptyLinePlaceholder":107},true,"\n",[47,110,112],{"class":49,"line":111},11,[47,113,114],{}," function parseDate(str) {\n",[15,116,117],{},"Let us break it down piece by piece.",[119,120,122],"h3",{"id":121},"file-headers","File Headers",[38,124,126],{"className":40,"code":125,"language":42,"meta":43,"style":43},"--- a\u002Fsrc\u002Futils\u002Fformat.js\n+++ b\u002Fsrc\u002Futils\u002Fformat.js\n",[19,127,128,132],{"__ignoreMap":43},[47,129,130],{"class":49,"line":50},[47,131,53],{},[47,133,134],{"class":49,"line":56},[47,135,59],{},[137,138,139,150],"ul",{},[140,141,142,145,146,149],"li",{},[19,143,144],{},"---"," marks the original file (often prefixed with ",[19,147,148],{},"a\u002F"," in Git).",[140,151,152,155,156,159],{},[19,153,154],{},"+++"," marks the modified file (prefixed with ",[19,157,158],{},"b\u002F",").",[119,161,163],{"id":162},"hunk-headers","Hunk Headers",[38,165,166],{"className":40,"code":65,"language":42,"meta":43,"style":43},[19,167,168],{"__ignoreMap":43},[47,169,170],{"class":49,"line":50},[47,171,65],{},[15,173,174,175,178],{},"The ",[19,176,177],{},"@@"," line is the hunk header. It tells you where this chunk of changes lives:",[137,180,181,190,198],{},[140,182,183,189],{},[184,185,186],"strong",{},[19,187,188],{},"-12,7"," — in the original file, this hunk starts at line 12 and spans 7 lines.",[140,191,192,197],{},[184,193,194],{},[19,195,196],{},"+12,7"," — in the modified file, this hunk starts at line 12 and spans 7 lines.",[140,199,200,201,204],{},"The trailing ",[19,202,203],{},"function formatDate(date)"," is a context line pulled from the file to help you locate the change visually.",[119,206,208],{"id":207},"change-lines","Change Lines",[210,211,212,225],"table",{},[213,214,215],"thead",{},[216,217,218,222],"tr",{},[219,220,221],"th",{},"Prefix",[219,223,224],{},"Meaning",[226,227,228,237,247],"tbody",{},[216,229,230,234],{},[231,232,233],"td",{},"(space)",[231,235,236],{},"Context line — unchanged, shown for reference",[216,238,239,244],{},[231,240,241],{},[19,242,243],{},"-",[231,245,246],{},"Line removed from the original",[216,248,249,254],{},[231,250,251],{},[19,252,253],{},"+",[231,255,256],{},"Line added in the modified version",[15,258,259,260,262,263,265],{},"A line that was modified appears as both a ",[19,261,243],{}," removal and a ",[19,264,253],{}," addition — the old content followed by the new content.",[10,267,269],{"id":268},"reading-multi-hunk-diffs","Reading Multi-Hunk Diffs",[15,271,272,273,275],{},"Large changes produce multiple hunks separated by their own ",[19,274,177],{}," headers:",[38,277,279],{"className":40,"code":278,"language":42,"meta":43,"style":43},"@@ -1,5 +1,6 @@\n import { format } from '.\u002Fformat';\n+import { validate } from '.\u002Fvalidate';\n\n const data = getData();\n-const result = format(data);\n+const result = format(validate(data));\n export default result;\n@@ -22,3 +23,8 @@\n   return output;\n }\n+\n+export function validate(input) {\n+  if (!input) throw new Error('Empty input');\n+  return input;\n+}\n",[19,280,281,286,291,296,300,305,310,315,320,325,330,334,340,346,352,358],{"__ignoreMap":43},[47,282,283],{"class":49,"line":50},[47,284,285],{},"@@ -1,5 +1,6 @@\n",[47,287,288],{"class":49,"line":56},[47,289,290],{}," import { format } from '.\u002Fformat';\n",[47,292,293],{"class":49,"line":62},[47,294,295],{},"+import { validate } from '.\u002Fvalidate';\n",[47,297,298],{"class":49,"line":68},[47,299,108],{"emptyLinePlaceholder":107},[47,301,302],{"class":49,"line":74},[47,303,304],{}," const data = getData();\n",[47,306,307],{"class":49,"line":80},[47,308,309],{},"-const result = format(data);\n",[47,311,312],{"class":49,"line":86},[47,313,314],{},"+const result = format(validate(data));\n",[47,316,317],{"class":49,"line":92},[47,318,319],{}," export default result;\n",[47,321,322],{"class":49,"line":98},[47,323,324],{},"@@ -22,3 +23,8 @@\n",[47,326,327],{"class":49,"line":104},[47,328,329],{},"   return output;\n",[47,331,332],{"class":49,"line":111},[47,333,101],{},[47,335,337],{"class":49,"line":336},12,[47,338,339],{},"+\n",[47,341,343],{"class":49,"line":342},13,[47,344,345],{},"+export function validate(input) {\n",[47,347,349],{"class":49,"line":348},14,[47,350,351],{},"+  if (!input) throw new Error('Empty input');\n",[47,353,355],{"class":49,"line":354},15,[47,356,357],{},"+  return input;\n",[47,359,361],{"class":49,"line":360},16,[47,362,363],{},"+}\n",[15,365,366],{},"Each hunk operates independently — line numbers are relative to that hunk's position, not the entire file.",[10,368,370],{"id":369},"context-lines","Context Lines",[15,372,373],{},"By default, unified diff shows 3 lines of context before and after each change. This helps you understand the surrounding code without opening the file. You can control the context width:",[38,375,379],{"className":376,"code":377,"language":378,"meta":43,"style":43},"language-bash shiki shiki-themes github-light github-dark","diff -U 5 old.txt new.txt   # 5 lines of context\ndiff -U 0 old.txt new.txt   # no context, just changes\n","bash",[19,380,381,404],{"__ignoreMap":43},[47,382,383,386,390,393,397,400],{"class":49,"line":50},[47,384,42],{"class":385},"sScJk",[47,387,389],{"class":388},"sj4cs"," -U",[47,391,392],{"class":388}," 5",[47,394,396],{"class":395},"sZZnC"," old.txt",[47,398,399],{"class":395}," new.txt",[47,401,403],{"class":402},"sJ8bj","   # 5 lines of context\n",[47,405,406,408,410,413,415,417],{"class":49,"line":56},[47,407,42],{"class":385},[47,409,389],{"class":388},[47,411,412],{"class":388}," 0",[47,414,396],{"class":395},[47,416,399],{"class":395},[47,418,419],{"class":402},"   # no context, just changes\n",[15,421,422,423,426],{},"Git respects this via the ",[19,424,425],{},"-U"," flag as well:",[38,428,430],{"className":376,"code":429,"language":378,"meta":43,"style":43},"git diff -U 10              # 10 lines of context\n",[19,431,432],{"__ignoreMap":43},[47,433,434,437,440,442,445],{"class":49,"line":50},[47,435,436],{"class":385},"git",[47,438,439],{"class":395}," diff",[47,441,389],{"class":388},[47,443,444],{"class":388}," 10",[47,446,447],{"class":402},"              # 10 lines of context\n",[10,449,451],{"id":450},"generating-and-applying-patches","Generating and Applying Patches",[15,453,454],{},"Unified diff output can be saved as a patch file and applied to the original:",[38,456,458],{"className":376,"code":457,"language":378,"meta":43,"style":43},"# Generate a patch\ngit diff > feature.patch\n\n# Apply it\ngit apply feature.patch\n",[19,459,460,465,478,482,487],{"__ignoreMap":43},[47,461,462],{"class":49,"line":50},[47,463,464],{"class":402},"# Generate a patch\n",[47,466,467,469,471,475],{"class":49,"line":56},[47,468,436],{"class":385},[47,470,439],{"class":395},[47,472,474],{"class":473},"szBVR"," >",[47,476,477],{"class":395}," feature.patch\n",[47,479,480],{"class":49,"line":62},[47,481,108],{"emptyLinePlaceholder":107},[47,483,484],{"class":49,"line":68},[47,485,486],{"class":402},"# Apply it\n",[47,488,489,491,494],{"class":49,"line":74},[47,490,436],{"class":385},[47,492,493],{"class":395}," apply",[47,495,477],{"class":395},[15,497,498],{},"This is how open-source projects accept contributions via email — contributors send unified diffs, maintainers review them, and apply them to the tree.",[10,500,502],{"id":501},"binary-and-special-cases","Binary and Special Cases",[15,504,505],{},"Unified diff is a text format. Binary files (images, compiled files) cannot be represented this way. Git marks them differently:",[38,507,509],{"className":40,"code":508,"language":42,"meta":43,"style":43},"Binary files a\u002Flogo.png and b\u002Flogo.png differ\n",[19,510,511],{"__ignoreMap":43},[47,512,513],{"class":49,"line":50},[47,514,508],{},[15,516,517,518,521],{},"New or deleted files use ",[19,519,520],{},"\u002Fdev\u002Fnull"," as one side:",[38,523,525],{"className":40,"code":524,"language":42,"meta":43,"style":43},"--- \u002Fdev\u002Fnull\n+++ b\u002Fnew-file.js\n@@ -0,0 +1,3 @@\n+export function hello() {\n+  return 'world';\n+}\n",[19,526,527,532,537,542,547,552],{"__ignoreMap":43},[47,528,529],{"class":49,"line":50},[47,530,531],{},"--- \u002Fdev\u002Fnull\n",[47,533,534],{"class":49,"line":56},[47,535,536],{},"+++ b\u002Fnew-file.js\n",[47,538,539],{"class":49,"line":62},[47,540,541],{},"@@ -0,0 +1,3 @@\n",[47,543,544],{"class":49,"line":68},[47,545,546],{},"+export function hello() {\n",[47,548,549],{"class":49,"line":74},[47,550,551],{},"+  return 'world';\n",[47,553,554],{"class":49,"line":80},[47,555,363],{},[10,557,559],{"id":558},"practical-tips","Practical Tips",[137,561,562,568,578,592],{},[140,563,564,567],{},[184,565,566],{},"Line numbers can shift"," — after the first hunk, line numbers in subsequent hunks refer to the modified file, not the original. Do not try to correlate line numbers across hunks.",[140,569,570,573,574,577],{},[184,571,572],{},"Whitespace changes"," — trailing whitespace in removed\u002Fadded lines is significant. Use ",[19,575,576],{},"git diff -w"," to ignore whitespace changes.",[140,579,580,583,584,587,588,591],{},[184,581,582],{},"Renamed files"," — Git detects renames and shows them as ",[19,585,586],{},"--- a\u002Fold-name.js"," \u002F ",[19,589,590],{},"+++ b\u002Fnew-name.js",".",[140,593,594,597],{},[184,595,596],{},"Combined diffs"," — merge commits produce a combined diff format with a third column prefix for the second parent.",[10,599,601],{"id":600},"key-takeaways","Key Takeaways",[137,603,604,607,623,626,635,638],{},[140,605,606],{},"Unified diff is the standard format for representing text changes, used by Git and all major version control systems.",[140,608,609,610,587,612,614,615,617,618,620,621,159],{},"Each diff contains file headers (",[19,611,144],{},[19,613,154],{},"), hunk headers (",[19,616,177],{},"), context lines (space prefix), removals (",[19,619,243],{},"), and additions (",[19,622,253],{},[140,624,625],{},"Hunk headers report start line and span for both the original and modified file.",[140,627,628,629,631,632,634],{},"Modified lines appear as a ",[19,630,243],{}," removal followed by a ",[19,633,253],{}," addition.",[140,636,637],{},"Context lines provide surrounding code for orientation without opening the file.",[140,639,640,641,591],{},"Unified diffs double as patch files — save the output and apply it with ",[19,642,643],{},"git apply",[10,645,647],{"id":646},"try-it-yourself","Try It Yourself",[15,649,650,651,591],{},"Paste two versions of text and see the unified diff instantly with the ",[652,653,655],"a",{"href":654},"\u002Ftools\u002Fdiff-checker","Diff Checker",[657,658,659],"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);}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}",{"title":43,"searchDepth":56,"depth":56,"links":661},[662,663,668,669,670,671,672,673,674],{"id":12,"depth":56,"text":13},{"id":32,"depth":56,"text":33,"children":664},[665,666,667],{"id":121,"depth":62,"text":122},{"id":162,"depth":62,"text":163},{"id":207,"depth":62,"text":208},{"id":268,"depth":56,"text":269},{"id":369,"depth":56,"text":370},{"id":450,"depth":56,"text":451},{"id":501,"depth":56,"text":502},{"id":558,"depth":56,"text":559},{"id":600,"depth":56,"text":601},{"id":646,"depth":56,"text":647},"2026-05-28","Read and interpret unified diff output — the standard format used by Git and patch tools.","md",{"immutable":107},"\u002Fguides\u002Funified-diff-format-explained",{"title":5,"description":676},"guides\u002Funified-diff-format-explained","Tv8SJ-M9nty1AzfCIZ6axeuLHJvmCzhhKE72qtnoNM8",1780401337840]