A per-repo, untracked `.gitignore-local`

You have files that you want to ignore, but that have no business being in the project's .gitignore: a a local test script, some draft assets. Adding them to .gitignore would mean committing your personal clutter for everyone. Leaving them alone means git status keeps nagging about untracked files.

Git has a built-in answer for this, .git/info/exclude, but it's tucked away inside .git/ where I never look, and I tend to forget what's in it. I wanted something visible, right at the root of the repo, that works the same way in all my local repositories.

Step 1: a global excludes file

Git lets you define an additional ignore file with core.excludesfile. Most people point it to a global file in their home directory. The trick here is to give it a relative path instead:

git config --global core.excludesfile .gitignore-local

Every repo now can have its own optional .gitignore-local, read just like a regular .gitignore, but never shared.

There's one catch: the .gitignore-local file itself shows up as untracked. The fix is to make it ignore itself, by having .gitignore-local as its first line:

.gitignore-local
# local files you want to ignore but not share via regular .gitignore:
test-script.py
assets/img/test-logo.png

Doing that by hand in every repo gets old fast.

Step 2: a git ignore-local alias

So here's an alias that takes care of it:

git config --global alias.ignore-local '!f() {
    file=.gitignore-local
    grep -qxF "$file" "$file" 2>/dev/null || echo "$file" >> "$file"
    [ $# -eq 0 ] && { cat "$file"; return; }
    for p in "$@"; do
        grep -qxF -- "$p" "$file" || echo "$p" >> "$file"
    done
}; f'

What it does:

  • Shell aliases (the ones starting with !) always run from the root of the repository, so the file lands in the right place even if you call the alias from a subdirectory.
  • If .gitignore-local doesn't exist yet, or exists without its self-ignoring line, that line is added.
  • Each pattern is appended only once, so no duplicates.
  • Called without arguments, it just prints the current list.

Usage

git ignore-local omgyes "*.mp3"   # ignore stuff locally
git ignore-local                  # show what's ignored

And git status stays clean:

On branch main
Your branch is up to date with 'origin/main'.

nothing to commit, working tree clean

If you ever wonder why a file is ignored, git check-ignore -v <file> tells you which rule matched and in which file.

Leave a Reply

Your email address will not be published. Required fields are marked *