# Git's Magic Files

# Git's Magic Files

**By Andrew Nesbitt** | February 5, 2026

Source: https://nesbitt.io/2026/02/05/git-magic-files.html

---

Git repositories contain special committed files that control version control behavior across the team. Unlike configuration stored in `.git/`, these "magic files" travel with your code and automatically affect how git treats your files.

## Core Git Magic Files

### .gitignore

Specifies patterns for files git should never track. Supports wildcards, directory markers, negation, and character ranges.

```
node_modules/
*.log
.env
dist/
```

Git checks multiple ignore files in sequence: `.gitignore` in each directory, `.git/info/exclude` for local-only ignores, and global ignore files. The `**` pattern matches nested directories. Note that ".gitignore only affects untracked files" — already-tracked files remain in the repository.

### .gitattributes

Configures how git handles specific files including filters, diff drivers, merge strategies, line ending normalization, and language detection.

```
*.psd filter=lfs diff=lfs merge=lfs
*.sh text eol=lf
*.png binary
package-lock.json merge=ours
vendor/* linguist-vendored
```

The `binary` attribute prevents diffing and merging. GitHub Linguist reads this file to override language detection and exclude vendored or generated code from statistics.

### .lfsconfig

Git LFS configuration that travels with the repository, specifying LFS endpoint URLs and transfer settings.

```
[lfs]
    url = https://lfs.example.com/repo
[lfs "transfer"]
    maxretries = 3
```

### .gitmodules

Configuration for git submodules, automatically created when running `git submodule add`.

```
[submodule "vendor/lib"]
    path = vendor/lib
    url = https://github.com/example/lib.git
    branch = main
```

Submodules embed other repositories as dependencies but don't handle versioning well and create nested `.git` directories.

### .mailmap

Maps author names and email addresses to canonical identities for `git log`, `git shortlog`, and `git blame` output.

```
Jane Developer <[email protected]> <[email protected]>
Jane Developer <[email protected]> Jane Dev <[email protected]>
```

Aggregates commits under proper identities. GitHub's contributor graphs don't use mailmap, so duplicates may persist online despite correct local mappings.

### .git-blame-ignore-revs

Lists commits that `git blame` should skip, useful for formatting changes and bulk updates.

```
# Ran prettier on entire codebase
a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0
```

Configure with `git config blame.ignoreRevsFile .git-blame-ignore-revs`. GitHub, GitLab (15.4+), and Gitea read this automatically.

### .gitmessage

A commit message template configured with `git config commit.template .gitmessage`. Requires manual setup per clone, unlike other magic files.

```
# <type>: <subject>
#
# <body>
#
# <footer>
#
# Types: feat, fix, docs, style, refactor, test, chore
```

## Forge-Specific Folders

Git forges use dedicated folders for their own configuration: `.github/`, `.gitlab/`, `.gitea/`, `.forgejo/`, `.bitbucket/`. These contain CI/CD workflows, issue templates, and CODEOWNERS files.

Forgejo checks `.forgejo/` → `.gitea/` → `.github/`. Gitea checks `.gitea/` → `.github/`. SourceHut uses `.build.yml` at the root.

## Other Conventions

**.gitkeep** — Git doesn't track empty directories. This convention file allows empty directories in repositories.

**.gitconfig** — Suggested configuration files (not auto-loaded for security) that developers can manually include.

**.gitsigners** — Tracks GPG/SSH signing keys for trusted contributors.

**.gitreview** — Configures Gerrit code review integration, specifying which server and project to push to.

**.gitlint** — Configuration for commit message linting that travels with the repository.

**.jj/** — Jujutsu VCS working copy directory, coexisting with `.git/` while respecting all git magic files.

## Related Tools and Conventions

**.editorconfig** — Standardizes editor behavior (indentation, line endings, charset) across teams.

```
[*]
indent_style = space
indent_size = 2
end_of_line = lf
```

**.ruby-version, .node-version, .python-version** — Version managers (rbenv, nvm, pyenv) read these to automatically switch language versions.

**.tool-versions** — asdf's multi-language version file format.

**.dockerignore** — Works like `.gitignore` for Docker build contexts, using identical syntax.

## Best Practices for Tool Development

If building tools that interact with git repositories, respect these files by:

- Reading `.gitignore` when traversing the repository
- Reading `.gitattributes` to identify binary, vendored, or generated files
- Reading `.mailmap` for author information
- Reading `.gitmodules` for submodule handling

Git's config format follows `[section "subsection"] key = value` syntax. Most languages have git config parsers available through their git libraries.
