First-time machine setup
Set your name, email, editor and default branch once with --global so every repository on the machine uses them.
Git · Command
git config reads, writes, and removes Git settings. These settings live in system, global (per-user), repository, and worktree config files, and they change how other Git commands behave.
Last updated
Each setting has a dotted name. The last dot-separated part is the variable, and everything before it is the section, optionally with a quoted subsection, for example remote.origin.url. When you read a setting without naming a scope, Git merges the system, global, local and worktree files in that order, and the last value it finds wins. When you write a setting, Git uses the repository's .git/config unless you pass --global, --system, --worktree or --file. Modern Git splits the work into subcommands: list, get, set, unset, rename-section, remove-section and edit. Flags such as --type, --value, --all and --show-origin refine how values are matched and printed.
git config get [<file-option>] [<display-option>] [--includes] [--all] [--regexp] [--value=<pattern>] [--fixed-value] [--default=<default>] [--url=<url>] <name>
git config set [<file-option>] [--type=<type>] [--all] [--value=<pattern>] [--fixed-value] <name> <value>
git config unset [<file-option>] [--all] [--value=<pattern>] [--fixed-value] <name>
git config list [<file-option>] [<display-option>] [--includes]| Name | Type | Description |
|---|---|---|
<name> | string | The setting's key, written as the section name and the variable name joined by a dot, with an optional subsection, for example core.filemode or http.<url>.sslVerify. |
<value> | string | The value to store with set. Git escapes it when writing it to the file. |
--global / --system / --local / --worktree / --file <config-file> | flag | Picks which config file to read from or write to. Writes go to the local repository file unless you choose another one. |
--value=<pattern> | string (extended regex) | Limits get, set and unset to entries whose current value matches the pattern. With --fixed-value the pattern must match the value exactly. |
--all | flag | With get, prints every value of a multi-valued key. With set or unset, replaces or removes all of them. |
--type=<type> | bool | int | bool-or-int | path | expiry-date | color | Checks values against the given type and converts them to its standard form, for example normalizing yes/on/1 to true. |
--default=<value> | string | With get, prints this value when the key is not set anywhere. |
--show-origin / --show-scope | flag | Shows the file (or other source) and the scope that each printed value came from. |
Exit code 0 on success. Failures return a non-zero code: 1 for an invalid or missing key, 2 when no section or name is given, 3 for an invalid config file, 4 when the file cannot be written, 5 when unsetting a key that does not exist or when several lines match, and 6 for an invalid regexp. get prints the value (or values) to stdout.
#!/usr/bin/env bash
set -euo pipefail
# Per-user defaults (written to ~/.gitconfig or $XDG_CONFIG_HOME/git/config)
git config set --global user.name "Ada Lovelace"
git config set --global user.email ada@example.com
git config set --global init.defaultBranch main
# Repo-specific override (written to .git/config by default)
git config set user.email ada@work.example.com
# Which value wins, and from where?
git config list --show-origin --show-scope | grep user.email
git config get user.email
# Typed read with a fallback when unset
git config get --type=bool --default=false commit.gpgSign
# Multi-valued key: append, read all, remove one by exact value
git config set --append remote.origin.fetch '+refs/tags/*:refs/tags/*'
git config get --all remote.origin.fetch
git config unset --fixed-value --value='+refs/tags/*:refs/tags/*' remote.origin.fetch
# Script-safe existence check (exit code 1 = not set)
if ! git config get core.editor >/dev/null; then
echo "core.editor not set"
fiRun inside a repository that has an origin remote: the script sets global and local values, shows which one wins and where it is stored, reads a typed value with a fallback, works with a multi-valued key, and checks whether a key exists using get's exit code.
Set your name, email, editor and default branch once with --global so every repository on the machine uses them.
Use a work email in one client repository by setting user.email locally, which overrides your personal global address.
Run list --show-origin --show-scope to find out which config file is setting an unexpected pull, editor or credential option.
Read settings with get --type and --default, or supply them through GIT_CONFIG_COUNT environment variables, so pipelines don't depend on a user's config files.
It uses the value in .git/config. Git reads the system file first, then the global (per-user) files, then the repository's file, and the last value it reads wins. A worktree's config.worktree is read after .git/config when worktree config is enabled, and settings passed with -c on the command line or through GIT_CONFIG_* variables override all of these files.
Follow-up: How would you prove which file supplied the value? Run git config get --show-origin --show-scope user.email (or list with the same flags). The output shows the file path and the scope for each value.
It is a key that appears on several lines, such as remote.origin.fetch or core.gitproxy. set and unset refuse to touch such a key by default. To target one line, pass --value=<pattern> (an extended regex), or add --fixed-value to match the value exactly. --append adds a new line without changing the existing ones.
Follow-up: How do you replace every line except one specific value? Put ! at the start of the --value pattern to match lines that do not match it, as in --value='! for '. This only works when --fixed-value is not used.
Some options are only honored when they come from protected configuration, meaning the system, global or command scope. Git treats those scopes as controlled by the user or a trusted administrator, while a repository's own config may come from somewhere less trustworthy. To make such an option take effect, set it with --global or --system, or pass it with -c.
Follow-up: How can a script inject config without touching any file? Set GIT_CONFIG_COUNT and the zero-indexed GIT_CONFIG_KEY_<n>/GIT_CONFIG_VALUE_<n> pairs. A missing key or value causes an error, and settings passed with git -c still take priority.
gitgit-worktreegit-helpgitrevisionsgit-initgit-commit