Where do the settings in my Git configuration come from?
Asked Answered
G

10

107

I've noticed that I have two listings for core.autocrlf when I run git config -l

$ git config -l
core.symlinks=false
core.autocrlf=false
color.diff=auto
color.status=auto
color.branch=auto
color.interactive=true
pack.packsizelimit=2g
help.format=html
http.sslcainfo=/bin/curl-ca-bundle.crt
sendemail.smtpserver=/bin/msmtp.exe
diff.astextplain.textconv=astextplain
rebase.autosquash=true
user.name=name
[email protected]
core.autocrlf=true

Those last three (from user.name down) are the only ones in my C:\users\username\.gitconfig file. Where are all of the other ones coming from? Why is core.autocrlf listed twice?

This is with MSysGit 1.8.3, and I also have Sourcetree installed (Windows 7). In Sourcetree I have unchecked the "Allow Sourcetree to modify your global Git config files"

Gunman answered 19/7, 2013 at 22:57 Comment(1)
Note: with git 2.8 (March 2016) and git config --list --show-origin, you won't have to guess which git config is where. See my answer belowJahnke
K
112

Git checks four places for a configuration file:

  1. Your machine's system .gitconfig file.
  2. Your user .gitconfig file located at ~/.gitconfig.
  3. A second user-specific configuration file located at $XDG_CONFIG_HOME/git/config or $HOME/.config/git/config.
  4. The local repository's configuration file .git/config.

The settings cascade in the following order, with each file adding or overriding settings defined in the file above it.

  1. System configuration.
  2. User configuration.
  3. Repository-specific configuration.

You can see what each file has defined using the following commands:

# System, applies to entire machine and all users
$ git config --system --list
$ git config --system --edit

# User defined
$ git config --global --list
$ git config --global --edit

You can see what just the repository-specific file has defined by opening up the file .git/config for that repository.

If you're using MSysGit on Windows, you'll probably find your user ~/.gitconfig file where ever %homepath% points to if you use echo %homepath% from a Windows command prompt.

From the documentation for git config:

If not set explicitly with --file, there are four files where git config will search for configuration options:

  • $(prefix)/etc/gitconfig

    System-wide configuration file.

  • $XDG_CONFIG_HOME/git/config

Second user-specific configuration file. If $XDG_CONFIG_HOME is not set or empty, $HOME/.config/git/config will be used. Any single-valued variable set in this file will be overwritten by whatever is in ~/.gitconfig. It is a good idea not to create this file if you sometimes use older versions of Git, as support for this file was added fairly recently.

  • ~/.gitconfig

User-specific configuration file. Also called "global" configuration file.

  • $GIT_DIR/config

    Repository specific configuration file.

If no further options are given, all reading options will read all of these files that are available. If the global or the system-wide configuration file are not available they will be ignored. If the repository configuration file is not available or readable, git config will exit with a non-zero error code. However, in neither case will an error message be issued.

The files are read in the order given above, with last value found taking precedence over values read earlier. When multiple values are taken then all values of a key from all files will be used.

All writing options will per default write to the repository specific configuration file. Note that this also affects options like --replace-all and --unset. git config will only ever change one file at a time.

You can override these rules either by command-line options or by environment variables. The --global and the --system options will limit the file used to the global or system-wide file respectively. The GIT_CONFIG environment variable has a similar effect, but you can specify any filename you want.

Karyn answered 19/7, 2013 at 23:3 Comment(6)
Where is the "machine's system .gitconfig file" when on Windows with msysgit?Deina
@Deina try C:\Program Files (x86)\Git\etc\gitconfig. Not sure if that's the right one though.Karyn
@Cupcake: Yeah, that was it. For some reason I can't modify that file though. Some process is holding onto it... can't figure out which one. I guess it doesn't matter since I can just override in the user-level configs. Thanks.Deina
For me, the "HOME" environment variable wasn't set (or was set to "/"), leading to git looking in a strange place for my global config. Using $>setx HOME "%USERPROFILE%" sorted it (as USERPROFILE is an existing environment variable that points to the correct location).Cervicitis
Current Git reads C:\Program Files\Git\mingw64\etc\gitconfigSociology
@KevinSmyth this changed recently to C:\Program Files\Git\etc\gitconfigLanguishment
J
81

You don't have to guess anymore which config has been set to where, with git 2.8! (March 2016)

See commit 70bd879, commit 473166b, commit 7454ee3, commit 7454ee3 (19 Feb 2016), commit 473166b, commit 7454ee3 (19 Feb 2016), commit 7454ee3 (19 Feb 2016), and commit a0578e0 (17 Feb 2016) by Lars Schneider (larsxschneider).
(Merged by Junio C Hamano -- gitster -- in commit dd0f567, 26 Feb 2016)

config: add '--show-origin' option to print the origin of a config value

If config values are queried using 'git config' (e.g. via --get, --get-all, --get-regexp, or --list flag) then it is sometimes hard to find the configuration file where the values were defined.

Teach 'git config' the '--show-origin' option to print the source configuration file for every printed value.

The git config man page will now indicates:

--show-origin:

Augment the output of all queried config options with the origin type (file, standard input, blob, command line) and the actual origin (config file path, ref, or blob id if applicable).

For example:

git config --list --show-origin

That will return:

    file:$HOME/.gitconfig   user.global=true
    file:$HOME/.gitconfig   user.override=global
    file:$HOME/.gitconfig   include.path=$INCLUDE_DIR/absolute.include
    file:$INCLUDE_DIR/absolute.include  user.absolute=include
    file:.git/config    user.local=true
    file:.git/config    user.override=local
    file:.git/config    include.path=../include/relative.include
    file:.git/../include/relative.include   user.relative=include
    command line:   user.cmdline=true

For one setting, as commented by wisbucky:

git config --show-origin --get-all core.autocrlf

    file:"D:\\prgs\\git\\latest\\mingw64/etc/gitconfig"     true
    file:C:/Users/vonc/.gitconfig   false

With Git 2.26 (Q1 2020), you can add the --show-scope option:

git config -l --show-origin --show-scope
Jahnke answered 27/2, 2016 at 14:28 Comment(6)
thank god. So many different articles online guessing at where git configs may have gotten stored. All articles missed one possible location that happened to be setup on my machine: c:\programdata\git\config. Don't know why its there, but i suspect Visual Studio's TFS integration. The other strange locations i spend way too much time looking for were: C:\program files\mingw64\etc\.gitconfig and H:\.gitconfig. Thank god for this new command. Jesus. Christ.Suffix
I wonder why user.cmdline=true is required for --show-origin to work? Also, I've noticed that --show-origin needs to be immediately after config in order to work with --get and --get-all. So it should be ... config --show-origin --get-all core.autocrlfSausauce
@Sausauce Agreed: I remove the -c 'user.cmdline=true' bit, which seems to refer to test scope: github.com/git/git/blob/…Jahnke
@Sausauce And I have included your example for one setting.Jahnke
@VonC, Ah seems like user.cmdline=true was necessary in Git 2.13, but no longer needed in Git 2.15.Sausauce
@Suffix The ProgramData config file is new and is indeed not being discussed much yet. I've only run into it so far over at stackoverflow.com/questions/32847697/…Pickle
R
10

After having previously installed Git for Windows and subsequently uninstalling it, I found that there is a configuration file installed at C:\Users\All Users\Git\config which is a system level configuration file which persists and will affect any future MinGW32 Git packages (in my case, I was running a portable MinGW32 Git package provided by my company). When I ran

git config --system --edit

it would show me the system configuration file located at mingw32/etc/gitconfig, but it would still load the values from the first location as well. This showed up as a warning that configuration values clashed when trying to use Git LFS.

WARNING: These git config values clash:
  git config "http.sslcainfo" = "C:/Users/foo/AppData/Local/Programs/Git/mingw64/ssl/certs/ca-bundle.crt"
  git config "http.sslcainfo" = "/ssl/certs/ca-bundle.crt"

(Note: this may also be a situation where LFS warnings are being too assertive, #861)

Ribal answered 12/12, 2015 at 0:39 Comment(2)
This is very useful. Would have never found that file at All Users. What did you do with it?Plymouth
I removed the 'Git' folders from C:\Users\All Users\ (an alias to C:\ProgramData) and C:\Users\foo\AppData\Local\Programs\ which removed all the left over configuration files.Ribal
J
7

In addition of git config -l --show-origin, that I presented here, with git 2.8 (March 2016), you now have, with Git 2.26 (Q1 2020)

git config -l --show-scope

# you can combine both options:
git config -l --show-origin --show-scope

git config learned to show in which "scope", in addition to in which file, each config setting comes from.

See commit 145d59f, commit 9a83d08, commit e37efa4, commit 5c105a8, commit 6766e41, commit 6dc905d, commit a5cb420 (10 Feb 2020), and commit 417be08, commit 3de7ee3, commit 329e6ec (24 Jan 2020) by Matthew Rogers (ROGERSM94).
(Merged by Junio C Hamano -- gitster -- in commit 5d55554, 17 Feb 2020)

config: add '--show-scope' to print the scope of a config value

Signed-off-by: Matthew Rogers

When a user queries config values with --show-origin, often it's difficult to determine what the actual "scope" (local, global, etc.) of a given value is based on just the origin file.

Teach 'git config' the '--show-scope' option to print the scope of all displayed config values.

Note that we should never see anything of "submodule" scope as that is only ever used by submodule-config.c when parsing the '.gitmodules' file.

Example:

git config -l --show-scope

global  user.global=true
global  user.override=global
global  include.path=$INCLUDE_DIR/absolute.include
global  user.absolute=include
local   user.local=true
local   user.override=local
local   include.path=../include/relative.include
local   user.relative=include

That allows you to quickly distinguish between:

  • Protected configuration: 'system', 'global', and 'command' scopes.
  • standard configuration: local to the repository.

This is introduced with Git 2.38 (Q3 2022):

See commit 8d1a744, commit 6061601, commit 5b3c650, commit 779ea93, commit 5f5af37 (14 Jul 2022) by Glen Choo (chooglen).
(Merged by Junio C Hamano -- gitster -- in commit 18bbc79, 22 Jul 2022)

Documentation: define protected configuration

Signed-off-by: Glen Choo

For security reasons, there are config variables that are only trusted when they are specified in certain configuration scopes, which are sometimes referred to on-list as 'protected configuration' (as in this thread).
A future commit will introduce another such variable (safe.bareRepository), so let's define our terms so that we can have consistent documentation and implementation.

In our documentation, define 'protected configuration' as the system, global and command config scopes.
As a shorthand, I will refer to variables that are only respected in protected configuration as 'protected configuration only', but this term is not used in the documentation.

This definition of protected configuration is based on whether or not Git can reasonably protect the user by ignoring the configuration scope:

  • System, global and command line config are considered protected because an attacker who has control over any of those can do plenty of harm without Git, so we gain very little by ignoring those scopes.
  • On the other hand, local (and similarly, worktree) config are not considered protected because it is relatively easy for an attacker to control local config, e.g.:
    • On some shared user environments, a non-admin attacker can create a repository high up the directory hierarchy (e.g. C:\.git on Windows), and a user may accidentally use it when their PS1 automatically invokes "git" commands.
      safe.directory prevents attacks of this form by making sure that the user intended to use the shared repository.
      It obviously shouldn't be read from the repository, because that would end up trusting the repository that Git was supposed to reject.
    • "git upload-pack"(man) is expected to run in repositories that may not be controlled by the user.
      We cannot ignore all config in that repository (because "git upload-pack" would fail), but we can limit the risks by ignoring uploadpack.packObjectsHook.

Only uploadpack.packObjectsHook is 'protected configuration only'.

The following variables are intentionally excluded:

  • safe.directory should be 'protected configuration only', but it does not technically fit the definition because it is not respected in the "command" scope.
    A future commit will fix this.
  • trace2.* happens to read the same scopes as safe.directory because they share an implementation.
    However, this is not for security reasons; it is because we want to start tracing so early that repository-level config and "-c" are not available.
    This requirement is unique to trace2.*, so it does not makes sense for protected configuration to be subject to the same constraints.

git config now includes in its man page:

Protected configuration

Protected configuration refers to the 'system', 'global', and 'command' scopes.
For security reasons, certain options are only respected when they are specified in protected configuration, and ignored otherwise.

Git treats these scopes as if they are controlled by the user or a trusted administrator. This is because an attacker who controls these scopes can do substantial harm without using Git, so it is assumed that the user's environment protects these scopes against attackers.


With Git 2.39 (Q4 2022), allow configuration files in "protected" scopes to include other configuration files.

See commit ecec57b (13 Oct 2022) by Glen Choo (chooglen).
(Merged by Junio C Hamano -- gitster -- in commit 777f548, 25 Oct 2022)

config: respect includes in protected config

Signed-off-by: Glen Choo

Protected config is implemented by reading a fixed set of paths, which ignores config [include]-s.
Replace this implementation with a call to config_with_options(), which handles [include]-s and saves us from duplicating the logic of 1) identifying which paths to read and 2) reading command line config.

As a result, git_configset_add_parameters() is unused, so remove it.
It was introduced alongside protected config in 5b3c650 ("config: learn git_protected_config()", 2022-07-14, Git v2.38.0-rc0 -- merge listed in batch #6) as a way to handle command line config.

Jahnke answered 18/2, 2020 at 17:24 Comment(0)
I
4

git config -l shows all inherited values from system, global, and local.

So you have another configuration file somewhere that is being loaded along with your user-defined .gitconfig file.

Infatuate answered 19/7, 2013 at 23:5 Comment(1)
Thanks, your answer clued me into the difference between system and global. @Cupcake's answer with the --system flags helped me find the file though.Gunman
X
4

You can use --show-origin in order to find out where the configurations come from.

Configuration files priority in Git for Windows:

...

$PROGRAMDATA/Git/config::
(Windows-only) System-wide configuration file shared with other Git implementations. Typically $PROGRAMDATA points to C:\ProgramData.

$(prefix)/etc/gitconfig::
System-wide configuration file. (Windows-only) This file contains only the settings which are specific for this installation of Git for Windows and which should not be shared with other Git implementations like JGit, libgit2. --system will select this file.

$XDG_CONFIG_HOME/git/config::
Second user-specific configuration file. If $XDG_CONFIG_HOME is not set or empty, $HOME/.config/git/config will be used. Any single-valued variable set in this file will be overwritten by whatever is in ~/.gitconfig. It is a good idea not to create this file if you sometimes use older versions of Git, as support for this file was added fairly recently.

~/.gitconfig::
User-specific configuration file. Also called "global" configuration file.

$GIT_DIR/config::
Repository specific configuration file.

...

The files are read in the order given above, with last value found taking precedence over values read earlier.

...

Source: https://github.com/git-for-windows/git/blob/master@%7B2018-01-07%7D/Documentation/git-config.txt#L231

$PROGRAMDATA is an environment variable. You can get the value of those variables like this:

In Git Bash you need to use echo "$ProgramData". In CMD, you need to use echo %PROGRAMDATA%. Note that Git Bash apparently pretends that environment variables are case sensitive.

What is $(prefix)?

The prefix is the top-level directory into which things get installed. In Git for Windows, that's either <some-path>/mingw64 or <some-path>/mingw32.

Xylography answered 1/3, 2019 at 15:29 Comment(0)
B
2

A complete answer for Windows (i.e. a Windows version of the accepted answer):

Like Linux, Windows has four levels of config files/settings and three are direct equivalents. The important thing to note is the other one - the 'All Apps/Users' one - particularly since this is where the installer sets values, e.g. 'core.autocrlf = true', and yet it can't be accessed from the command line so it causes confusion.

All Applications and Users

This is like a shared version of the ‘system’ settings in case you have multiple Git applications installed. There is no 'git config' command to access these, but they still impact the net result for a setting.

Configuration file location:

C:\ProgramData\Git\config

(Note that 'ProgramData' was 'All Users' on older versions of Windows.)

System

Configuration file location: C:/Program Files/Git/mingw64/etc/gitconfig

$ git config --system --list

User

Configuration file location: %USERPROFILE%.gitconfig (This resolves to 'C:/Users/<username>')

$ git config --global --list

Repository

Configuration file location: [current repository directory]/.git/config

$ git config --local --list
Biannual answered 28/8, 2019 at 19:21 Comment(0)
U
1

On Windows 7 (maybe the same or similar for Windows 10), for Visual Studio and the Git command line, your global configuration is in:

%USERPROFILE%\.gitconfig

(dot is in front of the file name)

But this is not honored by Sourcetree, at least in Git Embedded mode, and the configuration is in:

%USERPROFILE%\AppData\Local\Atlassian\SourceTree\git_local\mingw32\etc\gitconfig

(no dot in front of the file name)

(I needed to update both files to modify my global Git settings for Git command and Sourcetree.)

Another fun part. The Git hooks configuration was working from the AppData\Local\... location, but after more research via Process Monitor, I noticed somehow Sourcetree is also loading global from company mapped drive for my user.

This makes very little sense as very few applications lookup this location, but somehow Sourcetree does, so if you can't make it to work per location settings at Sourcetree, run Process Monitor and create a rule to log only path containing gitconfig, and you can find where really your global configuration is in case of a network-mapped user directory.

And this may not be even fault of Sourcetree, as I see now as I write this that git.exe is loading that, but this happens only for git.exe executed by Sourcetree, while a direct command line Git uses %USERPROFILE%\.gitconfig

Enter image description here

Finally I took all the results from Process Monitor, fed it into SQL Server and ran a query to get distinct results (no particular execution order just sorted by path):

Enter image description here

I don't know how those configurations relate to each-other, but I know some override another some settings works from one location some from another.

And the above list is invoked by Sourcetree, again direct a command line with Git seems to work fine with %USERPROFILE%\.gitconfig, and that is not on this list, but it would look like this (on Windows 7 ) C:\Users\pawel.cioch\.gitconfig

Ursine answered 24/4, 2019 at 21:50 Comment(0)
C
-1

If you want to find to find the actual file location, it'll be in your home directory.

It is hidden and preceded with a ".".

So if you're on a Mac, in your terminal you can cd ~ && open .gitconfig or open it with your favourite text editor, e.g cd ~ && atom .gitconfig.

Casteel answered 17/11, 2017 at 6:48 Comment(1)
This has already been said. No need to add confusion by suggesting a (non) alternative.Scheel
E
-1

In mac, it's /usr/local/git/etc/gitconfig -_-

Efflux answered 8/7, 2021 at 19:48 Comment(2)
Does not apply to all. Probably depends on how you've configured your git. Mine's at /usr/local/etc/gitconfig and at ~/.gitconfig. That's why it's better to just use --show-origin as described in the other answers.Stricker
good point, Gino. Thanks for this clarification!Efflux

© 2022 - 2024 — McMap. All rights reserved.