orome
orome

Reputation: 48516

Where should I place my global 'gitattributes' file?

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?

Upvotes: 90

Views: 59059

Answers (4)

Zhi Zhu
Zhi Zhu

Reputation: 69

I don't have enough reputation to comment. So I post an answer instead.

There's one kind of gitattributes which is not mentioned in the accepted answer: .gitattributes files in the work tree.

In Git - gitattributes Documentation:

When deciding what attributes are assigned to a path, Git consults $GIT_DIR/info/attributes file (which has the highest precedence), .gitattributes file in the same directory as the path in question, and its parent directories up to the toplevel of the work tree (the further the directory that contains .gitattributes is from the path in question, the lower its precedence). Finally global and system-wide files are considered (they have the lowest precedence).

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. Attributes which should be version-controlled and distributed to other repositories (i.e., attributes of interest to all users) should go into .gitattributes files.

If .gitattributes files in the work tree are not committed into the repository, they (though having lower precedence than) are similar to the $GIT_DIR/info/attributes file: they only affect the current repository.

If .gitattributes files in the work tree are committed into the repository, they affect all repositories which checked them out (if not overwritten by the $GIT_DIR/info/attributes file).

($GIT_DIR/info/attributes and .gitattributes files in the work tree are similar to $GIT_DIR/info/exclude and .gitignore files in the work tree.)

Upvotes: 2

VonC
VonC

Reputation: 1326696

You can also reference a global .gitattribute through new environment variables:

git var GIT_ATTR_GLOBAL

With Git 2.42 (Q3 2023), add more "git var"(man) for toolsmiths to learn various locations Git is configured with either via the configuration or hardcoded defaults.

See commit 4db16f5 (27 Jun 2023) by Jeff King (peff).
See commit ed773a1, commit 576a37f, commit 15780bb, commit cdd489e, commit f74c90d, commit 1e65721, commit d6546af (27 Jun 2023) by brian m. carlson (bk2204).
(Merged by Junio C Hamano -- gitster -- in commit 89d62d5, 04 Jul 2023)

var: add attributes files locations

Signed-off-by: brian m. carlson

Currently, there are some programs which would like to read and parse the gitattributes files at the global or system levels.
However, it's not always obvious where these files live, especially for the system file, which may have been hard-coded at compile time or computed dynamically based on the runtime prefix.

It's not reasonable to expect all callers of Git to intuitively know where the Git distributor or user has configured these locations to be, so add some entries to allow us to determine their location.
Honor the GIT_ATTR_NOSYSTEM environment variable if one is specified.
Expose the accessor functions in a way that we can reuse them from within the var code.

In order to make our paths consistent on Windows and also use the same form as paths use in "git rev-parse"(man), let's normalize the path before we return it.
This results in Windows-style paths that use slashes, which is convenient for making our tests function in a consistent way across platforms.
Note that this requires that some of our values be freed, so let's add a flag about whether the value needs to be freed and use it accordingly.

git var now includes in its man page:

GIT_ATTR_SYSTEM

The path to the system linkgit:gitattributes[5] file, if one is enabled.

GIT_ATTR_GLOBAL

The path to the global (per-user) linkgit:gitattributes[5] file.

Upvotes: 2

jack-a-la-hg
jack-a-la-hg

Reputation: 41

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.

Upvotes: 4

jub0bs
jub0bs

Reputation: 66344

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/.

Upvotes: 130

Related Questions