config: add "worktree" and "worktree/i" includeIf conditions
The includeIf mechanism already supports matching on the .git
directory path (gitdir) and the currently checked out branch
(onbranch). But in multi-worktree setups the .git directory of a
linked worktree points into the main repository's .git/worktrees/
area, which makes gitdir patterns cumbersome when one wants to
include config based on the working tree's checkout path instead.
Introduce two new condition keywords:
- worktree:<pattern> matches the realpath of the current worktree's
working directory (i.e. repo_get_work_tree()) against a glob
pattern. This is the path returned by git rev-parse
--show-toplevel.
- worktree/i:<pattern> is the case-insensitive variant.
The implementation reuses the include_by_path() helper introduced in
the previous commit, passing the worktree path in place of the
gitdir. The condition never matches in bare repositories (where
there is no worktree) or during early config reading (where no
repository is available).
Add documentation describing the new conditions, including a comparison
with extensions.worktreeConfig and a note that worktree matching currently
uses the realpath-resolved worktree location. Add tests covering bare
repositories, multiple worktrees, realpath-resolved symlinked worktree
paths, case-sensitive and case-insensitive matching, early config reading,
and non-repository scenarios.
Signed-off-by: Chen Linxuan <me@black-desk.cn>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Chen Linxuan committedJul 10, 2026 at 14:43 UTC5004829756596498a20305b3fce8387629396835
3 files changed+187
Documentation/config.adoc
+53
index 15b1a4d593..1ef72de62f 100644--- a/Documentation/config.adoc+++ b/Documentation/config.adoc@@ -146,6 +146,51 @@ refer to linkgit:gitignore[5] for details. For convenience: This is the same as `gitdir` except that matching is done case-insensitively (e.g. on case-insensitive file systems)+`worktree`::+ The data that follows the keyword `worktree` and a colon is used as a+ glob pattern. If the working directory of the current worktree matches+ the pattern, the include condition is met.+++The worktree location is the path where files are checked out (as returned+by `git rev-parse --show-toplevel`). This is different from `gitdir`, which+matches the `.git` directory path. In a linked worktree, the worktree path+is the directory where that worktree's files are located, not the main+repository's `.git` directory.+++The pattern uses the same glob syntax as `gitdir` (including `~/`, `./`,+`**/`, and trailing-`/` prefix matching). This condition will never match+in a bare repository (which has no worktree).+++Unlike `gitdir`, the `worktree` condition currently matches only the+realpath-resolved worktree location. If the working tree was entered via a+symbolic link, a pattern that uses the symbolic-link spelling may not match;+use the real path instead.+++This is useful when you want to apply configuration based on where the+working tree is located on the filesystem. For example, a contributor who+works on the same project both personally and as an employee can use+different `user.name` and `user.email` values depending on which directory+the worktree is checked out under:+++----+[includeIf "worktree:/home/user/work/"]+ path = ~/.config/git/work.inc+[includeIf "worktree:/home/user/personal/"]+ path = ~/.config/git/personal.inc+----+++While `extensions.worktreeConfig` (see linkgit:git-worktree[1]) also supports+per-worktree configuration, it stores the config inside each repository's+`.git/config.worktree` file and requires running `git config --worktree`+inside each worktree individually. In contrast, `includeIf "worktree:..."`+can be set once in a global or system-level configuration file (e.g.+`~/.config/git/config`) and applies to all repositories at once based on+their worktree location.++`worktree/i`::+ This is the same as `worktree` except that matching is done+ case-insensitively (e.g. on case-insensitive file systems)+ `onbranch`:: The data that follows the keyword `onbranch` and a colon is taken to be a pattern with standard globbing wildcards and two additional@@ -244,6 +289,14 @@ Example [includeIf "gitdir:~/to/group/"] path = /path/to/foo.inc+; include if the worktree is at /path/to/project-build+[includeIf "worktree:/path/to/project-build"]+ path = build-config.inc++; include for all worktrees inside /path/to/group+[includeIf "worktree:/path/to/group/"]+ path = group-config.inc+ ; relative paths are always relative to the including ; file (if the condition is true); their location is not ; affected by the condition