Git Config: How It Works and What to Set
A complete guide to git config — the three scopes, how values are resolved, the most useful settings, conditional includes for work vs personal machines, and how to inspect what is active.
The Three Scopes
Git config operates at three levels. Each level overrides the one above it.
| Scope | File location | Flag |
|---|---|---|
| System | /etc/gitconfig | --system |
| Global | ~/.gitconfig or ~/.config/git/config | --global |
| Local | .git/config inside the repo | --local |
System applies to every user on the machine. You rarely touch this.
Global applies to every repo for your user account. This is where you set your name, email, default editor, and personal preferences.
Local applies only to the current repository. It overrides global. Use it for per-project overrides, such as a different email for a work repo or a different default branch.
Reading Config Values
git config user.name # read a single value (local → global → system)
git config --global user.name # read from global scope only
git config --list # list all active values (merged across scopes)
git config --list --show-origin # same, but show which file each comes from
git config --list --show-scope # same, but show scope name (local/global/system)
--list --show-origin is the most useful debugging tool. It tells you exactly which file is providing each value and lets you spot conflicts.
Setting Values
git config --global user.name "Brian"
git config --global user.email "you@example.com"
git config --local user.email "work@company.com" # override for this repo only
To edit the config file directly in your editor:
git config --global --edit
Essential Settings
Identity
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
These appear in every commit you make. Without them, git uses system defaults which are often wrong.
Default branch name
git config --global init.defaultBranch main
Sets the branch name used when you run git init. Older git versions default to master.
Default editor
git config --global core.editor "code --wait" # VS Code
git config --global core.editor "vim"
git config --global core.editor "nano"
Used for commit messages, interactive rebases, and merge conflict resolution when git opens an editor.
Auto-prune on fetch
git config --global fetch.prune true
Removes stale remote-tracking refs automatically every time you git fetch. Equivalent to always passing --prune.
Push default
git config --global push.default current
current pushes the current branch to a remote branch of the same name, creating it if it doesn’t exist. The older default (matching) pushed all branches that existed on both sides, which caused surprising behaviour.
Other options: simple (safe default since git 2.0), upstream, nothing.
Pull behaviour
git config --global pull.rebase false # merge (default)
git config --global pull.rebase true # rebase instead of merge
git config --global pull.ff only # fast-forward only, fail otherwise
pull.ff only is the strictest. It refuses to pull if it can’t fast-forward, forcing you to rebase or merge manually. Good for keeping history clean.
Line endings (important on Windows/Mac teams)
git config --global core.autocrlf input # Mac/Linux: convert CRLF to LF on commit
git config --global core.autocrlf true # Windows: convert LF to CRLF on checkout
Rerere (reuse recorded resolution)
git config --global rerere.enabled true
Remembers how you resolved a merge conflict and reapplies the same resolution automatically if the same conflict appears again. Useful on long-running branches that frequently rebase onto main.
Colour output
git config --global color.ui auto
Enables coloured output in terminal when output goes to a terminal (not a pipe). Usually the default, but worth setting explicitly.
Aliases
Aliases let you define shorthand for commands you type frequently.
git config --global alias.st status
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.lg "log --oneline --graph --all"
git config --global alias.unstage "reset HEAD --"
git config --global alias.last "log -1 HEAD"
After setting these:
git st # git status
git lg # pretty log graph
git unstage src/foo.ts # unstage a file
Aliases can also run shell commands by prefixing with !:
git config --global alias.aliases "config --get-regexp alias"
# git aliases → lists all your aliases
Conditional Includes
If you use one machine for both personal and work projects, conditional includes let you automatically apply a different config depending on where the repo lives.
In ~/.gitconfig:
[includeIf "gitdir:~/personal/"]
path = ~/.gitconfig-personal
[includeIf "gitdir:~/work/"]
path = ~/.gitconfig-work
~/.gitconfig-personal:
[user]
email = personal@gmail.com
~/.gitconfig-work:
[user]
email = brian@company.com
signingKey = ABCD1234
The gitdir: condition matches based on the .git directory path of the current repo. If a repo is inside ~/work/, the work config is included and its values override the global ones.
You can also match on the remote URL with hasconfig:remote.*.url::
[includeIf "hasconfig:remote.*.url:git@github.com:mycompany/*"]
path = ~/.gitconfig-work
The Config File Format
The .gitconfig file is INI-style. Sections are in brackets, keys are indented under them.
[user]
name = Brian
email = you@example.com
[core]
editor = code --wait
autocrlf = input
[alias]
lg = log --oneline --graph --all
st = status
[fetch]
prune = true
[pull]
rebase = false
You can edit this directly. It’s just a text file. git config --global --edit opens it in your configured editor.
Unsetting and Removing Values
git config --global --unset user.email # remove a specific key
git config --global --remove-section alias # remove an entire section
Quick Reference
| Task | Command |
|---|---|
| See all active config with source | git config --list --show-origin |
| Set global identity | git config --global user.name / user.email |
| Override email for one repo | git config --local user.email "work@co.com" |
| Edit global config in editor | git config --global --edit |
| Auto-prune on fetch | git config --global fetch.prune true |
| Add an alias | git config --global alias.lg "log --oneline --graph" |
| Remove a value | git config --global --unset <key> |