Layered config: system, global, local, worktree. Learn the layers.
git config reads and writes the key/value store that controls every knob in Git, from your name on commits to whether pull rebases. It is the single source of truth for Git's behavior; learn the layers or be confused forever.
Pure text files. Nothing in the working tree, index, objects, or refs is touched. Config lives in plain INI-style files at four scopes (system, global, local, worktree) and is merged with later scopes overriding earlier ones at lookup time.
git config [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] name [value [value-pattern]]
git config [<file-option>] [--type=<type>] --add name value
git config [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get name [value-pattern]
git config [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get-all name [value-pattern]
git config [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get-regexp name_regex [value-pattern]
git config [<file-option>] --unset name [value-pattern]
git config [<file-option>] --unset-all name [value-pattern]
git config [<file-option>] --rename-section old_name new_name
git config [<file-option>] --remove-section name
git config [<file-option>] [--show-origin] [--show-scope] [-z|--null] -l | --list
git config [<file-option>] --get-color name [default]
git config [<file-option>] --get-colorbool name [stdout-is-tty]
git config [<file-option>] -e | --edit| Flag | What it does |
|---|---|
--system | Edit /etc/gitconfig. Affects every user on the box. |
--global | Edit ~/.gitconfig (or ~/.config/git/config). Per-user, normal default for personal settings. |
--local | Edit .git/config. Per-repo, default if you give no scope flag inside a repo. |
--worktree | Edit per-worktree config. Requires extensions.worktreeConfig=true. |
--add | Append a new line for a multi-value key instead of replacing it. |
--replace-all | ⚠️ Force a single value for a key that has multiple lines. Will silently nuke the others. |
--get-regexp | Dump all keys matching a regex. The right tool for finding what's set. |
<key> (highest-precedence layer wins).$ git config --get user.emailgit config <key> <value>); writes to local scope by default.$ git config user.email you@example.com<key>.$ git config --unset user.emailremote.<name>.url).$ git config --add remote.origin.url git@mirror:proj.git--show-origin shows which file each came from.$ git config --list --show-origin<pattern>.$ git config --get-regexp '^alias\.'$ git config --global --edit[section] block.$ git config --remove-section aliasroot@hostname.--show-origin and --show-scope.~/work/ uses your work email automatically.$ git config --global user.name "Linus T."
$ git config --global user.email "torvalds@example.org"
$ git config --global init.defaultBranch main
$ git config --global pull.rebase true$ git config --show-origin --show-scope --get user.email
# global file:/home/you/.gitconfig you@personal.tld
$ git config --show-origin --get-all remote.origin.fetch# in ~/.gitconfig
[includeIf "gitdir:~/work/"]
path = ~/.gitconfig-work
# then ~/.gitconfig-work
[user]
email = you@bigcorp.com$ git config --global alias.lg "log --oneline --graph --decorate --all"
$ git lguser.name, user.email, init.defaultBranch, pull.rebase, and push.default=simple once globally and forget about them.--show-origin --show-scope whenever a setting behaves weirdly. Guessing the scope wastes hours.includeIf for multi-identity setups. Do not script cd hooks to swap identities.git config foo.bar baz inside a repo writes to .git/config, not your global. Be explicit.remote..fetch, http.) silently break when you use plain --set. Use --add, --get-all, --unset-all, or --replace-all deliberately.Hit each option, then Check answers. Score is recorded; Next is always open.