77

I gather there is (despite the lack of documentation) a way to set Git attributes globally; but I'm not clear where to place the necessary gitattributes file. The instructions say they belong in

$(prefix)/etc/gitattributes

But where is $(prefix)? In particular, where would it be for OS X (with Git in /usr/local/git/bin/git)? Alternately (or in addition) would ~/.gitattributes work?

Community
  • 1
  • 1
orome
  • 40,124
  • 45
  • 174
  • 373
  • 3
    In a Git context, "global" usually means "user-level"; in other words, a *global* setting affect all repositories for *one* specific user. In contrast, a *system-wide* setting affects all repositories for *all* users of a machine. Which level is of interest to you? User-level or system-wide? – jub0bs Jan 19 '15 at 15:02
  • @Jubobs: Both (i.e., where to put one vs. the other; there also seem to be Git-version-specific locations as well, if one has more than one Git installed, as I do); but mostly for a user. – orome Jan 19 '15 at 15:03
  • For Windows see [Where does git config --global get written to?](http://stackoverflow.com/q/2114111) – Michael Freidgeim May 08 '16 at 12:52

2 Answers2

107

Global vs. system-wide settings

There is some ambiguity in your question's terminology. In a Git context, "global" usually means "user-level"; in other words, a global setting affect all repositories for one specific user (the active one). In contrast, a system-wide setting affects all repositories for all users of a machine.

Repository-level gitattributes

(I'm only mentioning this for completeness.)

According to the relevant section of the Pro Git book,

If you wish to affect only a single repository (i.e., to assign attributes to files that are particular to one user’s workflow for that repository), then attributes should be placed in the $GIT_DIR/info/attributes file.

$GIT_DIR would typically expand to <path-to-repo-root-directory>/.git.

Global (user-level) gitattributes

According to the relevant section of the Pro Git book,

Attributes that should affect all repositories for a single user should be placed in a file specified by the core.attributesfile configuration option [...]. Its default value is $XDG_CONFIG_HOME/git/attributes. If $XDG_CONFIG_HOME is either not set or empty, $HOME/.config/git/attributes is used instead.

You can also run the following command,

git config --global core.attributesfile <path>

to point Git to a custom path <path> for your global gitattributes file, e.g. ~/.gitattributes.

System-wide gitattributes

According to the relevant section of the Pro Git book,

Attributes for all users on a system should be placed in the $(prefix)/etc/gitattributes file.

which naturally begs the question:

[...] But where is $(prefix)?

See What is $(prefix) on $(prefix)/etc/gitconfig? for an answer. Unless you've assigned prefix a custom, non-empty value, $(prefix) expands to nothing by default; therefore, your system-wide gitattributes file should reside in /etc/.

jub0bs
  • 54,300
  • 24
  • 162
  • 166
  • I have a `/usr/local/git/etc` directory which seems to be respected for `gitattributes` (at least by `/usr/local/git/bin/git`) but no `/etc/git`. There's also a `~/.config/git` directory containing an ignore that GitHub seems to have generated). It's not clear to me how all of these fit together. – orome Jan 19 '15 at 17:51
  • @raxacoricofallapatorius The prefix used for compiling Git during the GitHub install may have been `/usr/local/git/`; if so, `/usr/local/git/etc/gitattributes` would be your *system-wide* gitattributes; see the *System-wide gitattributes* section in my answer. As for `~/.config/git`, that's your *global* gitattributes; see the *Global (user-level) gitattributes* section in my answer. – jub0bs Jan 19 '15 at 18:20
  • 1
    So (to check) any `etc` will be system wide (or at least system wide for a given Git) while the various `$XDG_CONFIG_HOME/git/...` or `~/.configs/git/..` won't matter (for `gitignore` either) if I've set `core.attributesfile` (or `core.excludesfile`) to something else. E.g., if I've set it to `/.gitattributes` (*viz.* `~/.gitignore`) that's what will be used for my "global" (user-level) settings. – orome Jan 19 '15 at 19:11
  • @raxacoricofallapatorius If I understand you correctly, the answer is no. Repository-level settings have precedence over user-level ones, which have precedence over system-wide settings. – jub0bs Jan 19 '15 at 19:29
  • Yes, and repo-level supersedes those. I was checking about "globals". – orome Jan 19 '15 at 19:41
  • @raxacoricofallapatorius Ok. Yes.The default path for global gitattributes, `$XDG_CONFIG_HOME/git/...`, won't be used if you override it by setting a custom path with to `git config --global core.attributesfile `. – jub0bs Jan 19 '15 at 19:46
  • Concerning `$(prefix)` note that your [linked question](https://stackoverflow.com/questions/19713622/what-is-prefix-on-prefix-etc-gitconfig)'s answer means `prefix` is taken at _compile_ time of `git`, not at run time – Tobias Kienzler Aug 04 '17 at 06:20
2

If you read this far and still don't know where $prefix is (i.e. it's not just blank or /usr/local) or why your /etc/gitattributes is not being read, you can use strace or similar tools to see all the places git is checking. Strace prints a huge amount of debug information on stderr, so use 2>&1 and filter it, as I do below, with grep. The git command I chose for the example uses an attributes file because of the --stat which changes based on a -diff attribute, but any git command you are trying to run at the time should be fine.

For example, with an updated git installed on RHEL using SCL, you could end up with this:

$ strace -f git log --stat -1 2>&1 | grep --color 'open.*attr'
open("/opt/rh/rh-git218/root/usr/etc/gitattributes", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/home/username/.config/git/attributes", O_RDONLY) = -1 ENOENT (No such file or directory)
open(".gitattributes", O_RDONLY)        = -1 ENOENT (No such file or directory)
open(".git/info/attributes", O_RDONLY)  = -1 ENOENT (No such file or directory)

. . . and that shows that the $prefix here is /opt/rh/rh-git218/root/usr.

Strace's -f is not necessary here but if you don't know and don't care whether some command is going to fork, adding -f in the first place can eliminate a chance you won't see what you are looking for.