git config --list prints every setting Git can see, merged from system, global and local files. git config --list --show-origin adds the file each one came from, and --show-scope labels the level — those two flags turn an unhelpful wall of text into an answer to why a setting is not what you expected.
Most people meet this command when something is configured wrong and they cannot find where. Your commits are attributed to the wrong email, line endings are being mangled, or a setting you clearly set is not taking effect.
The reason is almost always that Git reads several files in order and the later one wins. Knowing which file said what is the whole diagnosis.
Table of contents
- The commands
- The precedence order
- Settings actually worth checking
- Editing and removing
- The credential setting worth auditing
- How this fits the rest of the stack
- FAQ
The commands
git config --list # everything, merged
git config --list --show-origin # with the file each came from
git config --list --show-scope # with the level: system, global, local
git config --list --local # just this repository
git config --list --global # just your user config
git config --list --system # just the machine-wide config
git config user.email # read a single value
git config --get-all remote.origin.fetch # a key that can repeat
Newer Git also accepts subcommand spellings, which read better:
git config list
git config get user.email
git config set user.email [email protected]
The --list/--get forms are not going away, so use whichever you find first in your muscle memory.
The output most worth knowing:
$ git config --list --show-origin --show-scope | grep user.email
global file:/home/you/.gitconfig [email protected]
local file:.git/config [email protected]
Two values, and the local one wins. That single line of output answers the question people usually spend ten minutes on.
The precedence order
Git reads configuration from several places, and later ones override earlier ones:
- System —
/etc/gitconfig. Applies to every user on the machine. Set with--system, usually needs root. - Global —
~/.gitconfigor~/.config/git/config. Your user. Set with--global. - Local —
.git/configin the repository. Set with--local, which is the default when you are inside a repo. - Worktree —
.git/config.worktree, whenextensions.worktreeConfigis enabled. - Command line —
git -c user.email=x commit, which beats everything.
So a bare git config user.email [email protected] inside a repository writes to that repository only. That surprises people who meant to set it everywhere and did not pass --global.
There is also --includeIf, which conditionally pulls in another file based on the repository path. It is the clean solution to the work-versus-personal identity problem:
# in ~/.gitconfig
[user]
name = Your Name
email = [email protected]
[includeIf "gitdir:~/work/"]
path = ~/.gitconfig-work
# in ~/.gitconfig-work
[user]
email = [email protected]
Every repository under ~/work/ now uses the work email automatically, with no per-repository setup and nothing to forget. The trailing slash on the gitdir pattern matters.
Settings actually worth checking
Identity, because commits with the wrong email are annoying to fix later:
git config user.name
git config user.email
Make Git refuse to guess, so you get an error instead of a wrong attribution:
git config --global user.useConfigOnly true
Line endings, the source of diffs where every line changed:
git config core.autocrlf
# true -- Windows: CRLF locally, LF in the repository
# input -- macOS/Linux: LF in the repository, no conversion on checkout
# false -- no conversion at all
A .gitattributes file in the repository is better than relying on each developer’s setting, because it applies to everyone:
* text=auto eol=lf
Merge and pull behaviour, which changed defaults in Git 2.27 and produces a warning on every pull until set:
git config --global pull.rebase false # merge (the traditional default)
git config --global pull.rebase true # rebase
git config --global pull.ff only # refuse anything but a fast-forward
Editor, if you have ever been trapped in vim after a commit:
git config --global core.editor "code --wait"
Editing and removing
git config --global --edit # open the file in your editor
git config --global --unset user.email
git config --global --unset-all http.proxy # for keys with several values
git config --global --remove-section alias
Opening the file directly is often faster than a sequence of --unset calls, and it lets you see the structure. The format is INI and entirely hand-editable:
[user]
name = Your Name
email = [email protected]
[core]
editor = code --wait
[alias]
st = status -sb
lg = log --oneline --graph --decorate -20
A stale proxy setting is a classic one to hunt with --show-origin. It gets set during a stint on a corporate network, survives in the global config, and then every clone fails with a connection error long after the network is gone:
git config --list --show-origin | grep -i proxy
Similarly, url.<base>.insteadOf rewrites can be baked into a system config by a corporate installer and silently redirect your clones somewhere unexpected.
The credential setting worth auditing
One entry deserves specific attention because of what it stores:
git config --list --show-origin | grep credential
credential.helper = store writes credentials in plaintext to ~/.git-credentials. No encryption, no expiry. If that is set, your tokens are sitting in a readable file, and anything that backs up your home directory has copied them.
Better options, by platform:
- Windows —
manager, which uses the Windows Credential Manager. - macOS —
osxkeychain. - Linux —
libsecret, orcache --timeout=3600for a memory-only cache.
git config --global credential.helper manager # Windows
git config --global credential.helper osxkeychain # macOS
git config --global credential.helper libsecret # Linux
If you find store configured and have used it with a token, treat the token as exposed and rotate it. That is a two-minute job and a reasonable precaution given the file has no protection at all.
How this fits the rest of the stack
Configuration that comes from several files with a precedence order is a pattern you meet everywhere — Git here, but also shell profiles, PHP settings, and application environments. The debugging technique generalises: find the flag that tells you where a value came from, and the mystery usually ends there.
For deployments the equivalent question is which environment variables a running service actually received, as opposed to which ones you believe you set. RunxBuild keeps environment variables per service in the dashboard, with build and runtime logs per deploy, so what the running process was given is visible rather than inferred from several overlapping files. If you are pricing a service alongside its database and storage, the RunxBuild hosting calculator shows them individually.
Useful related references:
- SSHD Config: The Right /etc/ssh/sshd_config for Production
- WebSockets Behind Nginx: A Config That Survives Production
- SSH Keygen on Mac: Terminal, ed25519, and the Config File
- Services on RunxBuild
FAQ
How do I see all my Git settings?
git config --list prints every setting merged across all levels. Add --show-origin to see which file each came from and --show-scope to see whether it is system, global or local — those flags are what make the output diagnostic rather than just long.
Why does my Git config change not take effect?
Because a more specific level overrides it. Local repository config beats global, which beats system config. Run git config --list --show-origin | grep <setting> to see every value for that key and which file set it — the last one listed wins.
How do I use different email addresses for work and personal repositories?
Use a conditional include in ~/.gitconfig: an [includeIf "gitdir:~/work/"] section pointing at a second config file that sets the work email. Every repository under that path picks it up automatically, with nothing to remember per repository.
Where is the global Git config file?
~/.gitconfig, or ~/.config/git/config if that exists. On Windows it is in your user profile directory. Open it directly with git config --global --edit, which is often faster than a series of unset commands.
Is credential.helper store safe?
No — it writes credentials in plaintext to ~/.git-credentials with no encryption or expiry. Use manager on Windows, osxkeychain on macOS, or libsecret on Linux. If you have been using store with a token, rotate that token.