git config
TL;DR: git config is the command-line interface used to manage Git’s configuration variables. These configurations are stored as plain text files structured in an INI format across three main scopes: system-wide, user-global, and repository-local. Git parses these files sequentially, applying a cascading inheritance model where the most specific repository-level setting overrides broader global configurations.
What Does git config Actually Do?
Many developers treat git config as a command that updates a hidden system registry or contacts a remote database. In reality, Git’s configuration system is simple: it is a collection of flat, plain text files stored on your hard drive. The git config command is a command-line wrapper for writing, reading, and deleting key-value pairs in those text files.
The Cascading Precedence Model
When you execute a Git command, Git checks for configuration variables in a strict hierarchy. If a setting is defined in multiple files, Git resolves the conflict by using the value from the most specific configuration file it reads.
graph TD
System[System Level: /etc/gitconfig] -->|Overridden by| Global[Global Level: ~/.gitconfig]
Global -->|Overridden by| Local[Local Level: .git/config]
Local -->|Overridden by| Env[Environment Variables e.g., GIT_AUTHOR_NAME]
Env -->|Overridden by| Cmd[Command Line Flags e.g., -c user.name]
style System fill:#f2f2f2,stroke:#333
style Global fill:#e1f5fe,stroke:#0288d1
style Local fill:#e8f5e9,stroke:#388e3c
style Env fill:#fff9c4,stroke:#fbc02d
style Cmd fill:#ffe0b2,stroke:#f57c00
- System Level (
--system): Applies to all users and all repositories on the machine.- Path:
/etc/gitconfig(Unix) orC:\Program Files\Git\etc\gitconfig(Windows). - Access: Requires administrative/root permissions to modify.
- Path:
- Global Level (
--global): Applies to the active operating system user account. This is where you configure settings that should apply across all of your repositories (such as your default commit author identity).- Path:
~/.gitconfigor~/.config/git/config(Unix) orC:\Users\Username\.gitconfig(Windows).
- Path:
- Local Level (
--local): Applies to the active repository. This is stored directly inside the repository’s.git/folder and overrides all global and system settings.- Path:
.git/config - Note: This is the default scope for the
git configcommand if no scope flag is provided.
- Path:
- Worktree Level (
--worktree): Applies to a specific Git worktree. Useful when managing multiple active checkouts of a single repository.- Path:
.git/worktrees/<id>/config.worktree
- Path:
- Environment Variables: You can temporarily override any configuration file variable using environment variables, such as
GIT_AUTHOR_NAMEorGIT_COMMITTER_EMAIL. - Command-Line Parameters: You can pass one-off settings directly to commands using the
-cflag (e.g.,git -c user.email="temp@example.com" commit).
What Happens Inside .git/ (Hands-on exploration)
Let’s initialize a Git repository and inspect how configurations are written and resolved at the filesystem level.
Step 1: Inspect a Fresh Local Configuration
Initialize a new Git repository:
$ mkdir config-internals && cd config-internals
$ git init
Initialized empty Git repository in /home/admin/Code/config-internals/.git/
When git init is run, Git creates a default local configuration file at .git/config. Let’s view the default contents using cat:
$ cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
These core variables define how Git interacts with your filesystem:
repositoryformatversion = 0: Defines the repository’s database format version. If Git encounters a repository version higher than it supports, it will refuse to read it.filemode = true: Tells Git to track POSIX file executable bit changes (e.g., if you make a script executable viachmod +x).bare = false: Declares that this is a standard working repository containing checked-out files on disk. A “bare” repository contains only the Git administrative directory (usually for remote hosting servers) and has this set totrue.logallrefupdates = true: Instructs Git to maintain the reflog (a detailed history tracking where branch tips andHEADhave pointed over time, stored in.git/logs/).
Step 2: Write and Verify Local Configuration
Let’s write a local setting using the git config command:
$ git config --local user.email "local-dev@dotgit.dev"
Now let’s check .git/config to see what changed:
$ cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[user]
email = local-dev@dotgit.dev
The command created a new block: [user] with email = local-dev@dotgit.dev.
Step 3: Observe Cascading Resolution
Let’s configure our global identity so we have settings at both levels:
$ git config --global user.name "Ada Lovelace"
$ git config --global user.email "ada@example.com"
Let’s run git config --list --show-origin to see how Git lists these configurations along with the files they are stored in:
$ git config --list --show-origin
file:/home/admin/.gitconfig user.name=Ada Lovelace
file:/home/admin/.gitconfig user.email=ada@example.com
file:.git/config core.repositoryformatversion=0
file:.git/config core.filemode=true
file:.git/config core.bare=false
file:.git/config core.logallrefupdates=true
file:.git/config user.email=local-dev@dotgit.dev
When you commit a change in this directory:
- Git queries the configuration keys.
- It reads
user.namefrom/home/admin/.gitconfig(Ada Lovelace). - It reads
user.emailfrom both/home/admin/.gitconfigand.git/config. Because.git/configis read last, its value (local-dev@dotgit.dev) overrides the global setting.
Let’s verify the resolved configuration that Git uses for commits:
$ git config user.name
Ada Lovelace
$ git config user.email
local-dev@dotgit.dev
Detailed Command Options & Advanced Usage
1. The Structure of gitconfig Files
All gitconfig files are plain-text INI files. The syntax consists of sections, variables (keys), and values:
[section]
key = value
boolean-flag = true ; semicolons indicate comments
# hashtags also indicate comments
[section "subsection"] ; subsections must be double-quoted
nested-key = nested-value
You can manipulate these variables programmatically using the following commands:
- Set a value:
git config [--scope] key value - Read a value:
git config [--scope] key - Unset/Delete a value:
git config [--scope] --unset key - Edit the configuration file in your editor:
git config [--scope] --edit
2. Advanced Configuration Variables
Beyond setting your author name and email, Git allows customization of core behaviors:
A. Staging and Line Endings (core.autocrlf)
This setting manages carriage returns across platforms, as discussed in installing-git:
# Force Unix line endings globally
$ git config --global core.autocrlf input
B. Merge conflict helper caching (rerere.enabled)
“Rerere” stands for Reuse Recorded Resolution. When active, Git records how you resolved a merge conflict and automatically applies that exact resolution if it encounters the same conflict again.
# Enable conflict resolution recording
$ git config --global rerere.enabled true
C. Setting a Global Ignore File (core.excludesfile)
If you want to ignore certain files (like .DS_Store or .idea/ folders) in all repositories on your system without adding them to each project’s .gitignore file:
$ git config --global core.excludesfile ~/.gitignore_global
3. Shell Script Command Aliases
Git lets you create shortcuts (aliases) for complex commands.
# Create a shortcut for short log status
$ git config --global alias.st status -sb
Now, typing git st executes git status -sb.
You can also run external system shell commands instead of Git subcommands by prefixing the alias with an exclamation point (!):
# Commit and push in a single command alias
$ git config --global alias.sync "!git pull && git push"
When Git encounters the !, it starts a subshell (typically /bin/sh) and passes the rest of the alias string to it, allowing you to run custom bash scripts directly from the git binary.
Real-World Scenario: Conditional Configuration Inclusion
Many developers use the same laptop for both personal projects and corporate work. Committing to a corporate repository with a personal email (or to a personal GitHub project with a corporate email) is a common mistake.
To solve this, Git provides conditional configuration inclusion via includeIf.
Step 1: Create Organization-Specific Directories
Organize your workspace so that all work repositories are in one folder, and personal ones are in another:
~/personal/~/work/
Step 2: Create Custom Git Config Files
Create a file at ~/.gitconfig-personal:
[user]
email = alex@personaldomain.com
signingkey = B2837C9F
Create another file at ~/.gitconfig-work:
[user]
email = alex.developer@corporation.com
signingkey = D827C11A
Step 3: Configure includeIf in your Global Git Config
Open your main ~/.gitconfig and configure it to dynamically load the appropriate configuration based on the directory path of the active repository:
[user]
name = Alex Developer ; Default name used everywhere
[includeIf "gitdir:~/personal/"]
path = ~/.gitconfig-personal
[includeIf "gitdir:~/work/"]
path = ~/.gitconfig-work
When you work on projects inside ~/work/, Git matches the directory pattern and overrides the default configuration with your corporate email and GPG key. When working inside ~/personal/, it applies your personal settings automatically.
Common Pitfalls and Mistakes
1. Unsetting or Editing the Wrong Scope
The Mistake: You run git config --unset user.email inside a repository to update a global setting, but the command runs locally and unsets the local config instead.
The Fix: Always specify the scope (--global, --local, --system) when writing or deleting settings to prevent writing files to the wrong scope.
2. Typographical Errors in Aliases
The Mistake: Creating an alias with a typo:
$ git config --global alias.cmmit "commit -m"
Now, git cmmit works, but you cannot edit or delete it without knowing how to reference it.
The Fix: You can delete the alias by running:
$ git config --global --unset alias.cmmit
Alternatively, open the global configuration file directly using your editor:
$ git config --global --edit
You can clean up any typographical errors under the [alias] section of the configuration file.
3. Permission Errors When Using --system
The Mistake: Running git config --system core.editor nano returns a permission denied error.
The Fix: The system-level configuration is stored in root-protected files like /etc/gitconfig. To modify them, you must run the command with administrator rights:
$ sudo git config --system core.editor nano
Command Quick Reference
| Command | Action Scope | Target File |
|---|---|---|
git config --list | List all resolved configurations | Merged view of all files |
git config --list --show-origin | List configurations with source file paths | Merged view of all files |
git config --global user.name "Name" | Set global commit author name | ~/.gitconfig |
git config --global user.email "Email" | Set global commit author email | ~/.gitconfig |
git config --local user.email "Email" | Set local repository author email | .git/config |
git config --global --unset alias.name | Delete a global alias shortcut | ~/.gitconfig |
git config --global --edit | Open global config file in system editor | ~/.gitconfig |
git config --local --edit | Open local config file in system editor | .git/config |
FAQ (People Also Ask)
Where are Git configurations saved?
Git configuration files are saved as plain text files in three locations based on their scope:
- System:
/etc/gitconfig(Unix) orC:\Program Files\Git\etc\gitconfig(Windows). - Global:
~/.gitconfigor~/.config/git/config(Unix) orC:\Users\Username\.gitconfig(Windows). - Local:
.git/configwithin the root directory of the specific repository.
How do I configure Git to use a custom text editor?
You can configure Git’s default text editor (such as VS Code or Sublime Text) by setting the core.editor variable globally:
# For Visual Studio Code
$ git config --global core.editor "code --wait"
# For Notepad++ (on Windows)
$ git config --global core.editor "'C:/Program Files/Notepad++/notepad++.exe' -multiInst -notabbar -nosession -noPlugin"
The --wait flag tells Git to pause the terminal prompt until you close the editor window where you write your commit message.
How do I check where a Git setting is inherited from?
To identify the file path that configured a specific setting, run git config with the --show-origin and --show-scope flags:
$ git config --show-origin --show-scope user.email
This returns the file path (e.g., file:.git/config) and scope level (e.g., local) that resolved the requested setting.
Test Your Knowledge
Loading quiz…