Leveraging Git Hooks to Fix Markdown Issues Automatically


Recently, Jacob Tomlinson wrote an excellent post about a frustrating issue with Markdown titles: sometimes they don't render properly, even when they look fine in an editor.

The culprit? Non-breaking spaces (\xa0) sneaking in after the # characters instead of normal spaces (\x20). This often happens on macOS if you accidentally press + SPACE instead of just SPACE.

Jacob's post explains the problem in detail, but I wanted to take it a step further: How can we automatically prevent this from ever happening?

Automatically fixing non-breaking spaces with git hooks

If you edit markdown locally before committing to git, a pre-commit hook is an easy way to catch and fix this issue before it even reaches your repository.

A pre-commit hook is a small script that runs automatically before you commit files.

We can use it to scan all .md files for non-breaking spaces and replace them with normal spaces.

Pre-commit hook to fix markdown headings

Save the following script as .git/hooks/pre-commit in your repository:

#!/bin/bash

# Find and replace non-breaking spaces in all markdown files
find . -name "*.md" -type f -print0 | while IFS= read -r -d '' file; do
    if grep -q $'\xa0' "$file"; then
        echo "Fixing non-breaking spaces in: $file"
        sed -i '' 's/\xa0/ /g' "$file"
    fi
done

exit 0

Make it executable:

chmod +x .git/hooks/pre-commit

Now, every time you commit, this script will ensure that all markdown files in that repository have the correct spaces in headings.

Setting up a global git hook

If you want to take this a step further and avoid setting it up for each individual repo, you can configure a global git hook.

Create a directory for global hooks:

mkdir -p ~/.git-hooks

Move the script local pre-commit there:

mv /my-repo/.git/hooks/pre-commit ~/.git-hooks/pre-commit

Make it executable:

chmod +x ~/.git-hooks/pre-commit

Configure git to use the global hook directory:

git config --global core.hooksPath ~/.git-hooks

Now, every Git repository you work on will automatically apply this fix before committing - no more manual setup per project.

Linting markdown with markdownlint

While the git hook above solves this specific issue, it's also worth using a linter like markdownlint to catch other formatting problems.

NPM required

This does require npm to run, but if you frequently write markdown or need to maintain consistency across your documents, it's well worth it.

Installing markdownlint

Assuming you have npm installed already, install the package globally with:

npm install -g markdownlint-cli

Then, to manually check a markdown file:

markdownlint README.md
Default Values

If you don't set up your own ruleset for the linter, then it will use the default recommended values

To automatically fix issues:

markdownlint --fix README.md

Using markdownlint in a pre-commit hook

You can modify the global git hook to also run markdownlint before every commit:

#!/bin/bash

# Fix non-breaking spaces
find . -name "*.md" -type f -print0 | while IFS= read -r -d '' file; do
    if grep -q $'\xa0' "$file"; then
        echo "Fixing non-breaking spaces in: $file"
        sed -i '' 's/\xa0/ /g' "$file"
    fi
done

# Run markdownlint
if command -v markdownlint &> /dev/null; then
    echo "Running markdownlint..."
    markdownlint --fix .
fi

exit 0

With this setup, your markdown files will automatically be cleaned up and formatted before every commit.

Final Thoughts

Jacob's article highlights an issue that can be frustrating, especially when you're dealing with multiple markdown parsers.

But with git hooks and markdownlint, you can automate the fix and never worry about broken markdown titles again.

If you work with markdown often, setting up these tools once will save you countless hours of debugging or formatting.


Enjoyed this content? Fuel my creativity!

If you found this article helpful, you can keep the ideas flowing by supporting me. Buy me a coffee or check out my apps to help me create more content like this!

Coffee Check out my apps