Anything that reviews, applies, or renders a change needs a diff it did not produce itself. This category carries unified diffs and git-format patches across the cases that break naive parsers: renames, binary hunks, file modes, added and deleted files, CRLF-versus-LF changes, no-newline-at-end-of-file markers, and multi-file series. Conflict fixtures ship the three-way marker layout so merge tooling can be tested without staging a real merge. Alongside them sit the configuration files every repository carries — .gitignore, .gitattributes, .gitconfig, .gitmodules — plus commit-message and changelog samples for conventional-commit linters. Every path, author, and hash is fictional and deterministic, so a patch applies the same way on every machine.
The same change as the unified twin, emitted in the pre-unified context format: `*** before` and `--- after` blocks separated by a row of asterisks, with `!`, `+` and `-` change markers. Parsers that assume every diff starts with `---`/`+++` misread this one as a unified diff with no hunks.
The default output of bare `diff`: ed-style commands such as `3a4` with `<` and `>` bodies and no file headers at all. Tooling that identifies diffs by looking for `---`, `+++` or `@@` cannot even tell this is a diff, which is exactly what makes it a useful negative fixture.
A one-line file changed in place. Both ranges have length one, so the header is written `@@ -1 +1 @@` with no comma and no count — the abbreviation the unified format allows and that regexes of the form `-(\d+),(\d+)` fail to match.
Byte-for-byte the same diff as its LF twin except that every line ends CR LF, which is what a diff produced or saved on Windows looks like. Readers that compare a hunk line against expected content without stripping the CR find that no line matches.
The mirror of the added-file fixture: every line is a deletion and the new range is `+0,0`. A renderer that writes an empty file instead of unlinking it, or that reports the change as a truncation, fails this one.
Quilt, Debian and vendor trees check patches into the repository, so editing one produces a diff whose body is itself full of `+++`, `---` and `@@` lines and whose section heading is a `diff --git` line. Any scanner that finds file boundaries by searching for those tokens anywhere in the stream splits this single-file diff into several phantom files.
git appends the enclosing declaration after the closing `@@` of each hunk header. The text is free-form and is not part of the range, so a parser that splits the header on `@@` and takes the last field reads the function signature as a range.
The LF half of the line-ending twin pair: identical text content to the CRLF fixture, differing only in the terminator bytes. Diff the two downloads to see nothing but line-ending changes, and use the pair to score end-of-line normalisation.
The file itself is LF-terminated, but every removed line carries a literal CR as its last character because the change under review is a CRLF-to-LF conversion. Renderers that do not show the CR display a hunk in which every removed and added line looks identical.
A file created from nothing: the old side is `/dev/null` and the hunk header carries the zero-length range `-0,0`. Parsers that compute a 1-based start line from the old range produce line 1 instead of line 0 unless they special-case a zero count.
Neither version ends with a newline, so the marker appears twice in one hunk: once after the last removed line and once after the last added line. Parsers that treat the marker as a terminator rather than an annotation stop reading at the first one and lose the added line.
A one-line file is edited and loses its trailing newline in the process, so the marker follows the `+` line instead of the `-` line. Applying this and then re-diffing must not reintroduce the newline.
The before-state has no final newline and the after-state gains one, so the marker appears once, immediately after the last `-` line. The change is invisible in a rendered side-by-side view yet alters the file's bytes, which is why line-based comparators report a spurious no-op.
With git's default `core.quotepath`, a path containing non-ASCII bytes is wrapped in double quotes and each byte is written as a backslash-octal escape. A parser that takes the header text literally creates a directory called `caf\303\251` on disk.
A patch as it actually arrives in a mailing-list message: prose above it, a sign-off and an email signature below it, and a signature separator that looks like the start of a deletion. Extractors must find the diff without swallowing the surrounding text.
The same change with `core.quotepath=false`, so the path is written as raw UTF-8 and the header is not quoted. Compare with the quoted twin to confirm a parser resolves both spellings to the same file.
The exact inverse of the single-hunk fixture: the same edit expressed as a deletion instead of an insertion. Applying both in sequence must return the file to its original bytes, which makes this the fixture for `patch -R` and for revert paths.
One TypeScript module edited in 2 places at once, so the hunks are far enough apart not to merge. Use it to check that a parser advances its line cursor by the hunk header rather than by counting emitted lines.
One added guard line in a shell script, rendered as a POSIX `diff -u` with three lines of context and timestamped ---/+++ headers. The smallest complete unified diff, and the baseline the context-format and normal-format twins in this group encode identically.
The same edit as the zero-context fixture with ten lines of context, which merges the separate hunks into fewer, larger ones. Pair the two to check that a hunk-merging or context-trimming routine reaches the same applied result from either input.
Three unrelated files changed in a single diff stream, with no `diff --git` lines to mark the boundaries — the only separator is the next `---` header. Splitters that key on `diff --git` see one file here instead of three.
Indentation is converted from tabs to spaces and one line gains trailing whitespace, so the diff is large and the program is unchanged. It is the fixture for `-w`/`--ignore-all-space` handling and for review UIs that offer a hide-whitespace toggle.
`diff -U0` output: hunks contain nothing but +/- lines, and pure insertions produce ranges such as `-9,0`. Coverage and blame tools that need zero-context diffs hit this shape constantly, and hunk mergers that assume at least one context line get the offsets wrong.
The machine-generated twin of the hand-written changelog: version headings that are themselves compare links, a leading warning glyph on the breaking-changes section, and every entry ending in a short-hash link back to the commit. The hashes are the same fictional ids used by the log fixtures in this category.
A hand-maintained changelog in the Keep a Changelog layout: an Unreleased section, dated version headings in square brackets, the standard change-type subheadings, and reference-style compare links at the bottom. It describes the same releases as the generated twin in this group, so a converter between the two can be scored.
A breaking change announced twice, which the specification allows: a `!` after the scope and a `BREAKING CHANGE:` footer whose value continues onto a second line. Generators that stop a footer at the first newline lose half the sentence, and version bumpers that only look for one of the two markers under-bump the release.
An intentionally invalid commit message that breaks four commitlint rules at once: no conventional type, a 116-character header, no blank line separating subject from body, and a body that starts mid-sentence. Every rule should fire independently, which is what makes this useful for checking that a linter reports all violations rather than stopping at the first.
A commit message file exactly as `git commit` hands it to a commit-msg hook: a conventional subject, a wrapped body, two trailers, and git's own comment block that the hook must ignore. The subject is 43 characters, comfortably inside commitlint's default 72-character header limit.
The stable machine format of git blame: a full header block the first time a commit appears and a bare `<sha> <old> <new>` line every time after, with each source line following on a tab-prefixed line. A parser that expects the header on every group loses the author of every line after the first.
Per-commit file lists with single-letter status codes, tab-separated. Rename rows are the trap: `R100` is followed by TWO paths instead of one, so a splitter that takes field 2 as the filename reports the old path for renames and the new path for everything else.
Machine-readable insertion and deletion counts per file. Two rows break naive arithmetic: the binary file reports `-` in both numeric columns rather than 0, and the rename path is brace-compressed into `docs/{README.md => guide.md}` rather than written out twice.
Six commits as `git log --oneline` prints them: an abbreviated hash, a space, and the subject line. Every subject follows Conventional Commits, including one with a `!` breaking marker, so a release-notes generator can be scored against a known answer.
The default `git log` format for the same six commits: full 40-character hashes, Author and Date headers, and message bodies indented by exactly four spaces with genuinely empty separator lines. One commit carries a `BREAKING CHANGE:` footer and another a `Fixes:` footer, which is the shape a changelog generator has to find.
The author-grouped summary git generates for release notes: a name, a commit count in parentheses, and the subjects indented by six spaces. The counts here are what the .mailmap fixture in this category produces after coalescing aliases, so the two files can be used together.
Porcelain v1 output covering staged-only, worktree-only, added, renamed, deleted, unmerged, untracked and ignored entries. The two status characters are positional and a space is meaningful, so trimming the line before parsing turns ' M' (modified but unstaged) into 'M' (staged).
The v2 format for the same working tree: `# branch.*` headers first, then one record per entry whose leading character selects a completely different field layout. Rename records put the new path first and separate the two paths with a TAB rather than an arrow, and unmerged records carry three object ids instead of two.
What `git show` prints for a merge commit: a `diff --cc` header, an index line naming three blobs, `@@@` hunk markers, and two prefix columns instead of one. The `++` line is the giveaway a reviewer is looking for — content that appears in the merge result but in neither parent.
An octopus merge, so the hunk marker grows to `@@@@` and every line carries three prefix columns. Any parser that hard-codes `@@@` or assumes two columns reads the third column as the first character of the line's content.
When the file mode differs between the parents and the merge result, a combined diff adds a `mode a,b..result` line below the index line — a comma-separated shape that appears nowhere else in git's output. Parsers written for the single-parent `old mode`/`new mode` pair do not recognise it.
The same conflict with `merge.conflictStyle=diff3`, which inserts the merge base between the two sides behind a row of pipes. Tools that split a conflict on `=======` alone silently fold the ancestor text into the ours side.
Someone committed a file that still contained conflict markers, and merging that commit produced markers inside markers. Region matchers that pair the first `<<<<<<<` with the first `=======` split this file in the wrong place and produce two overlapping regions that cannot both be resolved.
Documentation about merge conflicts that quotes the markers inside a fenced code block, and then genuinely conflicts further down. A pre-commit hook that greps for `^<<<<<<<` reports two hits and blocks a clean commit; one that understands Markdown fences reports the one that matters.
One file left with three independent unresolved regions and clean text between them, which is what a real deployment-values merge looks like. Editors that jump to 'the next conflict' and resolvers that report a boolean rather than a count both get exercised here.
A working-tree file left mid-merge in git's default `merge` conflict style: our version, a row of equals signs, their version, and branch labels on the opening and closing markers. Both sides happen to end with the same line, which the zdiff3 twin in this group hoists out and this style repeats.
The identical merge under `merge.conflictStyle=zdiff3`, which hoists lines common to both sides out of the conflict region — here 'jitter: on' moves below the closing marker. Diff this against the diff3 twin to see that the same conflict produces different file contents depending on one config value.
The message template git writes into .git/MERGE_MSG when a merge stops on conflicts: one real subject line followed by a commented list of the conflicted paths and the standard advice block. Everything after the first blank line is stripped by `git commit`, so a hook that lints the whole file rejects messages git would accept.
The `.orig` backup GNU patch writes beside a file it has modified: the exact pre-patch content, kept so a failed application can be unwound. Paired with the .rej fixture, it is the complete state a developer actually finds after a patch goes wrong.
A package manifest left mid-merge, so the file is intentionally invalid JSON: conflict markers sit inside the dependencies object. Any tool that reads manifests has to fail on this with a message about the conflict rather than a bare syntax error at line 5.
What `git apply --reject` leaves behind when a hunk will not apply: the failed hunks alone, under a header that is neither `diff --git` nor a plain `---`/`+++` pair. Ships with its .orig twin so the pair can drive a resolve-the-reject workflow end to end.
The `--cover-letter` message git writes ahead of a series: a `[PATCH 0/3]` subject, a shortlog of the authors and their subjects, and the combined diffstat — but no diff of its own. Series tooling has to recognise it as metadata and not try to apply it.
Patch 1 of a three-message series, threaded under the cover letter with In-Reply-To and References headers. Applying the three out of order breaks: the series is only self-consistent in numeric order.
Patch 2 of a three-message series, threaded under the cover letter with In-Reply-To and References headers. Applying the three out of order breaks: the series is only self-consistent in numeric order.
Patch 3 of a three-message series, threaded under the cover letter with In-Reply-To and References headers. Applying the three out of order breaks: the series is only self-consistent in numeric order.
The same four messages concatenated into a single mbox, which is exactly what `git format-patch --stdout` produces and what `git am` consumes. The From_ separator lines use git's fixed sentinel date, so a splitter cannot rely on the timestamp being real.
The `index` line abbreviates both blob ids to seven characters, which is what plain format-patch emits and what most patches in the wild carry. Three-way application can still fall back to path matching, but the blobs cannot be looked up unambiguously in a large repository.
The commit message uses `---` as a horizontal rule, so the file contains two lines that look like the diffstat separator. git's own mailinfo ends the message at the FIRST one, which quietly truncates the message and drops the rounding table — the patch still applies, but the recorded history is wrong.
`copy from`/`copy to` headers, produced only when copy detection is enabled with `-C`. The source file still exists afterwards, which is the whole difference from a rename — and the difference a parser that maps both header pairs onto one 'moved' concept silently erases.
The whole patch file uses CRLF terminators, as it would after a round trip through a Windows editor or a mail client. `git am` needs `--keep-cr` to be told the CRs belong to the patch rather than to the content, and the `-- ` signature line now ends with space-CR-LF.
A deletion of an executable file, so the `deleted file mode 100755` header records the mode the file had rather than the mode to create. A patcher that writes an empty file here instead of unlinking leaves a broken executable behind.
format-patch output for a commit created with `--allow-empty`: full mail headers, a commit message, the `---` separator, and then straight to the signature with no diffstat and no diff. Pipelines that treat 'no diff found' as a parse error reject a message that git itself considers valid.
The torture test: one commit that creates a file, deletes an executable, renames at 100%, copies with detection on, changes a mode while editing, and adds a binary blob. The diffstat carries the matching create/delete/rename/mode-change summary lines that follow the file table.
The same patch with `--full-index`, so both blob ids are the complete 40 hex characters. This is what `git apply --3way` needs to find the pre-image blob, and comparing the two twins shows a parser must accept any hash length between 4 and 40.
A real binary file carried inside a text patch: zlib-deflated, encoded in git's own base85 alphabet, split into length-prefixed lines, and followed by the reverse `literal 0` payload that makes the patch revertible. The index line uses full 40-character hashes because `--binary` implies `--full-index`, and the recorded blob sha1 is the genuine object id of the attached PNG.
An intentionally invalid patch whose hunk header claims 99 lines on each side while the body supplies far fewer. Every other byte is a well-formed patch, so this isolates one question: does the applier verify the declared counts, or does it trust them and read past the end of the hunk?
An intentionally invalid patch: the file ends three lines into a hunk that declares many more, as it would after a truncated download or a mail client cutting the message. Nothing is corrupt at the byte level, so a parser must notice the count mismatch rather than applying a partial hunk.
The LF half of the patch twin pair, identical in text content to the CRLF fixture. Diff the two downloads to get a change that is invisible in every renderer and fatal to a byte comparison.
The same file changes permissions and content in one commit, so the mode headers are followed by an `index` line and a normal hunk. Applying only the hunk and silently ignoring the mode is the common failure, and it leaves a script that is no longer executable.
A permission change and nothing else: the file section has `old mode`/`new mode` headers, no `index` line, no `---`/`+++` pair and no hunks at all. Parsers that require at least one hunk per file drop this change entirely and report an empty patch.
A file creation carried by the `new file mode 100644` extended header rather than by the paths alone. The mode is the authoritative signal: the `--- /dev/null` line tells you the old side is empty, but only the header tells you what permissions to create the file with.
A rename with no content change at all: `similarity index 100%`, `rename from`, `rename to`, and then nothing — no index line and no hunks. This is the single most common patch shape that naive parsers lose, because there is no `@@` anywhere in the file section.
A rename that also edits the file, so the similarity index drops to 68% and the rename headers are followed by an index line and real hunks whose `---`/`+++` paths differ from each other. A patcher that applies hunks to the path on the `---` line writes to the file that no longer exists.
Non-ASCII in the author name and the subject, so both are Q-encoded into `=?UTF-8?q?...?=` words and the subject is folded across two lines with a leading space. The body is left as raw UTF-8, which means one message needs two different decoders.
A patch sent as a reply: the mail subject starts with `Re:`, quoted text sits above a `-- >8 --` scissors line, and the real commit subject and body sit below it. `git am --scissors` discards everything above the cut; a parser that trusts the mail Subject header records 'Re: [PATCH] ...' as the commit title.
A complete format-patch message: the mbox `From <sha> Mon Sep 17 00:00:00 2001` line, RFC 5322 headers, a commit message with a Signed-off-by trailer, the `---` separator, a diffstat and the diff. The signature separator is `-- ` with the trailing space git actually writes, which editors love to strip.
Git stores a symlink as a blob whose contents are the link target with no trailing newline, so this patch adds a single + line followed by the no-newline marker and marks it mode 120000. A patcher that ignores the mode writes a regular text file containing a path.
An intentionally invalid ownership file carrying five defects that all parse as plausible lines: an owner that is neither a handle nor an email, a team with no organisation, a character class, a negation, and a path with an unescaped space. Each is a separate assertion for a linter, and none of them is a syntax error a naive line splitter would notice.
Deliberately overlapping rules so every interesting path matches two or three of them, which is the only way to test that a resolver applies last-match-wins rather than most-specific-wins. One rule has no owners at all, which clears inherited ownership instead of adding any.
The attribute file that decides what happens to line endings on checkout: `text=auto` as the default, explicit `eol=lf` and `eol=crlf` overrides, the `binary` macro that expands to `-text -diff`, and one `-text` entry that is still given a textconv driver. This is the file whose absence causes the CRLF twins elsewhere in this category.
The non-EOL half of the format: LFS filter/diff/merge triples, `linguist-generated` and `linguist-vendored` hints that hide files from language statistics and review, `export-ignore` entries that drop paths from `git archive`, and a `merge=union` driver for an append-only changelog. Attribute values are unquoted and space-separated, so column alignment is whitespace a parser must collapse.
Every conditional-include form git supports — path prefix, case-insensitive path prefix, branch glob, and a condition on an existing remote URL — plus one unconditional include. Order matters: a later include overrides an earlier one, so a parser that gathers includes into a set rather than a list resolves the wrong identity.
A realistic global config exercising the whole INI-like grammar: bracketed sections, quoted subsection names that are case-sensitive while section names are not, values with size suffixes, a shell alias whose leading `!` changes how the rest is executed, and both comment characters.
Every escape the format defines, including the one nobody expects: a trailing space is stripped from a pattern unless it is backslash-escaped, so `draft\ ` and `draft` ignore different files. Editors that trim trailing whitespace on save silently change what this file means.
One pattern per rule in the gitignore grammar: a leading slash that anchors to the containing directory, the same name unanchored, `**` in all three positions, `?` and `[...]` classes, and a trailing slash that matches only directories. Every line is a separate assertion for a matcher's test suite.
The single most misunderstood rule in the format: once `build/` excludes a directory, git does not descend into it, so `!build/keep.txt` is dead. The file is valid and the behaviour is documented — it is the author's expectation that is wrong, which is exactly why an ignore-matcher must reproduce it rather than being helpful.
A realistic monorepo ignore file that uses `dist/*` rather than `dist/` precisely so the two `!dist/...` re-inclusions below it can work. It also carries the `.env.*` / `!.env.example` and `*.log` / `!logs/retained/*.log` pairs that every ignore-matcher has to order correctly.
The corrected twin: `build/*` excludes the directory's contents instead of the directory, so git still descends and `!build/keep.txt` re-includes the file. The two fixtures differ by two characters and produce opposite results, which makes them a precise pass/fail pair for an ignore engine.
Three submodules covering the awkward values: a relative `../currency-tables.git` URL that has to be resolved against the superproject's remote, `branch = .` meaning 'the same branch as the superproject', and `ignore = dirty` which hides a submodule's local changes from `git status`. The section name and the `path` value are separate strings and are allowed to differ.
One line for each of the four rewrite forms git's mailmap supports, including the two-pair form that matches on the commit name as well as the email. Four aliases collapse onto three canonical authors, which is exactly the transformation a shortlog or contributor report has to reproduce.
Renames, file-mode changes, binary hunks, added and deleted files, CRLF↔LF changes, no-newline-at-end-of-file markers, and multi-file patch series.
Can I actually apply these patches?+
The patch fixtures are self-consistent unified diffs with documented target paths, so they apply cleanly against the stated before-state. Conflict fixtures ship the three-way marker layout instead, for merge tooling.
Do you ship real repository history?+
No. Every author, path, hash, and timestamp is fictional and deterministic — nothing here is extracted from a real repository.
We use Google Analytics and show ads via Adsterra. Non-essential cookies and ad scripts run only after you allow the matching categories. See our cookie policy.