Sashmark / Blog

Why agent Markdown diffs get noisy, and how to shrink them

Bobby Huang ·

Agent-written Markdown diffs get noisy when more than the real edit changes: the whole file is rewritten, paragraphs are re-wrapped, line endings flip between LF and CRLF, trailing spaces or the final newline change, list and emphasis markers swap, or a tool reformats on save. To read past the noise, use git diff --word-diff, --ignore-cr-at-eol, -w and --stat, and stage only the real change with git add -p. To stop it, set *.md text eol=lf in .gitattributes, set line endings and the final newline in .editorconfig, write one sentence per line, turn off format-on-save for Markdown, and tell your agent to edit only the lines the task needs.

Key takeaways

  • Diff noise comes from changes nobody asked for: re-wrapping, line endings, whitespace, marker swaps and whole-file rewrites.
  • git diff --word-diff, --ignore-cr-at-eol, -w and --stat help you find the real change inside a noisy diff.
  • git add -p lets you commit the real edit and leave the noise out.
  • A .gitattributes line, an .editorconfig file, one sentence per line and clear agent instructions stop these causes before they start.
  • Sashmark is in development and not released; its clean Round-Trip save and a Changes View are planned for v1.

You asked your agent to fix one line in a plan file. It did. Then you open the Markdown diff and the whole file is red and green. Somewhere in there is the line you care about, but you have to hunt for it, and you can't be sure nothing else changed.

That noise has a short list of causes: line endings, wrapping, whitespace and tools that rewrite files instead of editing them. Some leave the rendered page unchanged. Others, like a change in indentation or trailing spaces, can change how it renders. Once you know the causes, you can read past them with git today and stop many of them before they start.

Why agent-written Markdown diffs get noisy

Each cause below changes bytes in the file without changing what you meant. Git compares lines, so any changed byte marks the whole line as changed.

The whole file is rewritten. You asked for one line. The agent read the file, made the change in memory and wrote every line back out. If anything else differs in how it wrote those lines, the diff grows.

Asked for: change "status: draft" to "status: final"
Got: every line in the file marked as changed

Paragraphs are re-wrapped. A paragraph that was broken at one width comes back broken at another. Every line in it now ends at a different word.

Before: The review is due Friday. The budget
        section is still open.
After:  The review is due Friday. The
        budget section is still open.

Line endings switch. One tool saved the file with CRLF line endings, the next with LF. The text looks the same on screen, and every line is still "changed."

Trailing spaces are added or removed. A space at the end of a line is invisible in most views, but it is a byte, and git sees it.

The final newline is added or dropped. One tool ends the file with a newline, another doesn't. The last line shows as changed, sometimes with a "No newline at end of file" note.

List or emphasis markers change. A list written with * comes back with -. Emphasis written as *word* comes back as _word_. The page renders the same; the bytes don't.

Before: * Draft the summary
After:  - Draft the summary

Table pipes are re-padded. A tool lines up the columns of a table by adding or removing spaces around the pipes. Change one cell and every row of the table can move.

Before: | Task | Owner |
After:  | Task      | Owner |

A tool reformats on save. An editor or formatter rewrites the file into its own house style every time it saves. Why editors reformat Markdown on save covers how that happens and what it changes.

How to see the real change in a noisy diff

Git already has the tools for this, and they cost nothing. For a full walk-through of git diffs on Markdown, with sample output, read how to diff Markdown files with git. Here is the short routine for a noisy agent edit.

  1. Check the size first. Run git diff --stat. It lists each changed file with a count of changed lines. A file that was rewritten end to end stands out right away.
  2. Hide line-ending noise. Run git diff --ignore-cr-at-eol. Lines whose only change is a carriage return at the end (CRLF vs LF) drop out of the view.
  3. Hide whitespace noise. Run git diff -w (the same as --ignore-all-space) to ignore whitespace when comparing lines. If you only want to ignore changes at the end of a line, use --ignore-space-at-eol instead. Whitespace can matter in Markdown, though: indentation can change a list or a code block, and two trailing spaces make a line break. Check those lines without -w before you dismiss them as noise.
  4. Read re-wrapped prose word by word. Run git diff --word-diff. It shows changes word by word inside a line, which makes a re-wrapped paragraph much easier to read.
  5. Commit only the real edit. Run git add -p. It lets you stage the change hunk by hunk, so you can keep the real edit and leave the noise out of the commit. When one hunk holds both, press s to split it into smaller hunks, or e to edit the hunk by hand. If both changes sit on the same line, s can't separate them, so use e or fix the line in your editor. Then run git diff --cached to review exactly what you staged before you commit.
git diff --stat
git diff --ignore-cr-at-eol -w notes.md
git diff --word-diff notes.md
git add -p notes.md

These flags only change what you see. The file on disk still has the noise. That's fine for reading, but if the same noise shows up on every agent run, fix it at the source.

How to stop Markdown diff noise at the source

Each step below removes one cause. You don't need all of them on day one. Start with the ones that match the noise you see.

1. Pin line endings with .gitattributes

Add this line to a .gitattributes file at the root of the repo:

*.md text eol=lf

It tells git to store Markdown with LF line endings and check it out with LF.

Start from a clean working tree, with no other edits waiting. Then stage .gitattributes and run git add --renormalize . to re-stage the files git already tracks under the new rule. Check what is staged with git diff --cached --stat before you commit. Commit that as its own change, with nothing else in it, so it doesn't hide real edits.

git status
git add .gitattributes
git add --renormalize .
git diff --cached --stat
git commit -m "Normalize Markdown line endings"

2. Set the basics in .editorconfig

An .editorconfig file at the repo root can set line endings and the final newline for Markdown. Editors and tools that support EditorConfig follow it.

[*.md]
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = false

Be careful with trim_trailing_whitespace on Markdown. Two spaces at the end of a line are a hard line break, so trimming them can change how the file renders. Set it to false for *.md, as above.

3. Write one sentence per line

Put each sentence on its own line (sometimes called semantic line breaks). A change to one sentence then stays on one line in the diff, and re-wrapping has nothing to move. Markdown still renders the lines as one paragraph, because a single line break inside a paragraph doesn't start a new one.

4. Turn off format-on-save for Markdown

If your editor formats on save, turn that off for Markdown files. If you do want a house style, run the formatter once across the repo as its own commit. Keeping formatting changes in their own commit makes later content edits easier to review.

5. Tell your agent to make targeted edits

Your agent reads an instruction file before it works. Add a few lines that ask for small, targeted edits and for the existing formatting to stay as it is. How to write Markdown docs your AI agent can follow covers how to set up that file so the agent actually uses it.

Lines like these are a good start:

## Editing Markdown files

- Edit only the lines the task needs.
- Keep the existing line wrapping.
- Do not reformat lists or tables.
- Keep the existing list and emphasis markers.
- Keep LF line endings and the final newline.
- Do not add or remove trailing spaces.

Keep the rules short and plain. If a diff still comes back noisy, check it against the list and add the rule that was missing.

A quick check after each agent run

Before you commit an agent's changes, run through this:

  • git diff --stat shows a change the size I expected.
  • git diff --ignore-cr-at-eol -w leaves only real edits.
  • I staged the real edit with git add -p if anything else was mixed in.
  • Any one-time cleanup (line endings, formatting) went in its own commit.

Where Sashmark fits

Git helps after a file changes. The tool you read and edit in decides whether your own saves add noise. A good reader should save only what you changed, so lines you did not edit stay byte for byte the same. Sashmark is being built for this; the roadmap shows where it stands. Sashmark's clean Round-Trip is planned for v1. What is a byte-for-byte round-trip save? explains the term.

A good reader should also show what changed since you last looked, without needing git. Sashmark's Changes View is planned for v1 to do that. Seeing what changed in a Markdown file covers the wider options.

Sashmark is a Markdown reader and editor for people whose AI agents write Markdown, being built for Mac, Windows and Linux. It is in development and has not been released, and the app has no AI features of its own. The planned features page lists what it is meant to do.

Sashmark is in development. See what it is at sashmark.com.

Questions

Why does my agent's one-line change show the whole file as changed?
Check whether the agent wrote the whole file back out instead of editing one line, and whether something else changed on the way, such as line endings, wrapping or the final newline. Run git diff --stat to confirm the size of the change, then git diff --ignore-cr-at-eol or -w to see whether the extra lines are only whitespace.
Should I set trim_trailing_whitespace to true for Markdown files?
Be careful. Two spaces at the end of a line are a hard line break in Markdown, so trimming them can change how the file renders. For *.md files, set trim_trailing_whitespace to false.
How do I commit only the real edit when the diff also has noise?
Use git add -p. It walks you through the change hunk by hunk, so you can stage the hunk with the real edit and skip the hunks that are only formatting.

What Sashmark plans for v1: Features · Roadmap

View as Markdown