Git development
 help / color / mirror / Atom feed
* [PATCH v4 0/2] includeIf: add "worktree" condition for matching working tree path
@ 2026-05-13  8:08 Chen Linxuan via B4 Relay
  2026-05-13  8:08 ` [PATCH v4 1/2] config: refactor include_by_gitdir() into include_by_path() Chen Linxuan via B4 Relay
  2026-05-13  8:08 ` [PATCH v4 2/2] config: add "worktree" and "worktree/i" includeIf conditions Chen Linxuan via B4 Relay
  0 siblings, 2 replies; 4+ messages in thread
From: Chen Linxuan via B4 Relay @ 2026-05-13  8:08 UTC (permalink / raw)
  To: git
  Cc: Kristoffer Haugsbakk, Junio C Hamano, Patrick Steinhardt,
	Chen Linxuan, Phillip Wood

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 against a glob pattern.
  - `worktree/i:<pattern>` is the case-insensitive variant.

Supported pattern features: glob wildcards, `**/` and `/**`, `~`
expansion, `./` relative paths, and trailing-`/` prefix matching.
The condition never matches in a bare repository.

Signed-off-by: Chen Linxuan <me@black-desk.cn>
---
Changes in v4:
- Deduplicate the worktree pattern documentation by referencing the
  gitdir syntax instead of repeating the full pattern description
  (suggested by Patrick Steinhardt).
- Add documentation comparing includeIf "worktree:" with
  extensions.worktreeConfig, including a concrete use case example
  (suggested by Phillip Wood, Junio C Hamano).
- Add a test verifying that the worktree condition does not match
  during early config reading (suggested by Patrick Steinhardt).
- Add tests for the non-repository (nongit) scenario (suggested by
  Patrick Steinhardt).
- Add a test for the case-insensitive "worktree/i" variant
- Link to v3: https://lore.kernel.org/r/20260403-includeif-worktree-v3-0-109ce5782b03@black-desk.cn

Changes in v3:
- Apply Junio's suggestion.
- Link to v2: https://lore.kernel.org/r/20260402-includeif-worktree-v2-0-36e339b898d7@black-desk.cn

Changes in v2:

- Add missing signed-off-by lines.
- Link to v1: https://lore.kernel.org/r/20260401-includeif-worktree-v1-0-906db69f2c79@black-desk.cn

---
Chen Linxuan (2):
      config: refactor include_by_gitdir() into include_by_path()
      config: add "worktree" and "worktree/i" includeIf conditions

 Documentation/config.adoc |  48 ++++++++++++++++++++
 config.c                  |  25 +++++-----
 t/t1305-config-include.sh | 113 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 175 insertions(+), 11 deletions(-)
---
base-commit: 270e10ad6dda3379ea0da7efd11e4fbf2cd7a325
change-id: 20260401-includeif-worktree-fcb64950dfba

Best regards,
-- 
Chen Linxuan <me@black-desk.cn>



^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH v4 1/2] config: refactor include_by_gitdir() into include_by_path()
  2026-05-13  8:08 [PATCH v4 0/2] includeIf: add "worktree" condition for matching working tree path Chen Linxuan via B4 Relay
@ 2026-05-13  8:08 ` Chen Linxuan via B4 Relay
  2026-05-13  8:08 ` [PATCH v4 2/2] config: add "worktree" and "worktree/i" includeIf conditions Chen Linxuan via B4 Relay
  1 sibling, 0 replies; 4+ messages in thread
From: Chen Linxuan via B4 Relay @ 2026-05-13  8:08 UTC (permalink / raw)
  To: git
  Cc: Kristoffer Haugsbakk, Junio C Hamano, Patrick Steinhardt,
	Chen Linxuan, Phillip Wood

From: Chen Linxuan <me@black-desk.cn>

The include_by_gitdir() function matches the realpath of a given
path against a glob pattern, but its interface is tightly coupled to
the gitdir condition: it takes a struct config_options *opts and
extracts opts->git_dir internally.

Refactor it into a more generic include_by_path() helper that takes
a const char *path parameter directly, and update the gitdir and
gitdir/i callers to pass opts->git_dir explicitly.  No behavior
change, just preparing for the addition of a new worktree condition
that will reuse the same path-matching logic with a different path.

Signed-off-by: Chen Linxuan <me@black-desk.cn>
---
 config.c | 19 ++++++++-----------
 1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/config.c b/config.c
index 156f2a24fa00..7d5dae0e8450 100644
--- a/config.c
+++ b/config.c
@@ -235,23 +235,20 @@ static int prepare_include_condition_pattern(const struct key_value_info *kvi,
 	return 0;
 }
 
-static int include_by_gitdir(const struct key_value_info *kvi,
-			     const struct config_options *opts,
-			     const char *cond, size_t cond_len, int icase)
+static int include_by_path(const struct key_value_info *kvi,
+			   const char *path,
+			   const char *cond, size_t cond_len, int icase)
 {
 	struct strbuf text = STRBUF_INIT;
 	struct strbuf pattern = STRBUF_INIT;
 	size_t prefix;
 	int ret = 0;
-	const char *git_dir;
 	int already_tried_absolute = 0;
 
-	if (opts->git_dir)
-		git_dir = opts->git_dir;
-	else
+	if (!path)
 		goto done;
 
-	strbuf_realpath(&text, git_dir, 1);
+	strbuf_realpath(&text, path, 1);
 	strbuf_add(&pattern, cond, cond_len);
 	ret = prepare_include_condition_pattern(kvi, &pattern, &prefix);
 	if (ret < 0)
@@ -284,7 +281,7 @@ static int include_by_gitdir(const struct key_value_info *kvi,
 		 * which'll do the right thing
 		 */
 		strbuf_reset(&text);
-		strbuf_add_absolute_path(&text, git_dir);
+		strbuf_add_absolute_path(&text, path);
 		already_tried_absolute = 1;
 		goto again;
 	}
@@ -400,9 +397,9 @@ static int include_condition_is_true(const struct key_value_info *kvi,
 	const struct config_options *opts = inc->opts;
 
 	if (skip_prefix_mem(cond, cond_len, "gitdir:", &cond, &cond_len))
-		return include_by_gitdir(kvi, opts, cond, cond_len, 0);
+		return include_by_path(kvi, opts->git_dir, cond, cond_len, 0);
 	else if (skip_prefix_mem(cond, cond_len, "gitdir/i:", &cond, &cond_len))
-		return include_by_gitdir(kvi, opts, cond, cond_len, 1);
+		return include_by_path(kvi, opts->git_dir, cond, cond_len, 1);
 	else if (skip_prefix_mem(cond, cond_len, "onbranch:", &cond, &cond_len))
 		return include_by_branch(inc, cond, cond_len);
 	else if (skip_prefix_mem(cond, cond_len, "hasconfig:remote.*.url:", &cond,

-- 
2.53.0



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH v4 2/2] config: add "worktree" and "worktree/i" includeIf conditions
  2026-05-13  8:08 [PATCH v4 0/2] includeIf: add "worktree" condition for matching working tree path Chen Linxuan via B4 Relay
  2026-05-13  8:08 ` [PATCH v4 1/2] config: refactor include_by_gitdir() into include_by_path() Chen Linxuan via B4 Relay
@ 2026-05-13  8:08 ` Chen Linxuan via B4 Relay
  2026-05-13 13:59   ` Phillip Wood
  1 sibling, 1 reply; 4+ messages in thread
From: Chen Linxuan via B4 Relay @ 2026-05-13  8:08 UTC (permalink / raw)
  To: git
  Cc: Kristoffer Haugsbakk, Junio C Hamano, Patrick Steinhardt,
	Chen Linxuan, Phillip Wood

From: Chen Linxuan <me@black-desk.cn>

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.  Add tests covering bare repositories,
multiple worktrees, symlinked worktree paths, case-insensitive matching,
early config reading, and non-repository scenarios.

Signed-off-by: Chen Linxuan <me@black-desk.cn>
---
 Documentation/config.adoc |  48 ++++++++++++++++++++
 config.c                  |   6 +++
 t/t1305-config-include.sh | 113 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 167 insertions(+)

diff --git a/Documentation/config.adoc b/Documentation/config.adoc
index 62eebe7c5450..6299b1e3a019 100644
--- a/Documentation/config.adoc
+++ b/Documentation/config.adoc
@@ -146,6 +146,46 @@ 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).
++
+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 +284,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
diff --git a/config.c b/config.c
index 7d5dae0e8450..6d0c2d0725e4 100644
--- a/config.c
+++ b/config.c
@@ -400,6 +400,12 @@ static int include_condition_is_true(const struct key_value_info *kvi,
 		return include_by_path(kvi, opts->git_dir, cond, cond_len, 0);
 	else if (skip_prefix_mem(cond, cond_len, "gitdir/i:", &cond, &cond_len))
 		return include_by_path(kvi, opts->git_dir, cond, cond_len, 1);
+	else if (skip_prefix_mem(cond, cond_len, "worktree:", &cond, &cond_len))
+		return include_by_path(kvi, inc->repo ? repo_get_work_tree(inc->repo) : NULL,
+				       cond, cond_len, 0);
+	else if (skip_prefix_mem(cond, cond_len, "worktree/i:", &cond, &cond_len))
+		return include_by_path(kvi, inc->repo ? repo_get_work_tree(inc->repo) : NULL,
+				       cond, cond_len, 1);
 	else if (skip_prefix_mem(cond, cond_len, "onbranch:", &cond, &cond_len))
 		return include_by_branch(inc, cond, cond_len);
 	else if (skip_prefix_mem(cond, cond_len, "hasconfig:remote.*.url:", &cond,
diff --git a/t/t1305-config-include.sh b/t/t1305-config-include.sh
index 6e51f892f320..07b6fb649cd2 100755
--- a/t/t1305-config-include.sh
+++ b/t/t1305-config-include.sh
@@ -396,4 +396,117 @@ test_expect_success 'onbranch without repository but explicit nonexistent Git di
 	test_must_fail nongit git --git-dir=nonexistent config get foo.bar
 '
 
+# worktree: conditional include tests
+
+test_expect_success 'conditional include, worktree bare repo' '
+	git init --bare wt-bare &&
+	(
+		cd wt-bare &&
+		echo "[includeIf \"worktree:/\"]path=bar-bare" >>config &&
+		echo "[test]wtbare=1" >bar-bare &&
+		test_must_fail git config test.wtbare
+	)
+'
+
+test_expect_success 'conditional include, worktree multiple worktrees' '
+	git init wt-multi &&
+	(
+		cd wt-multi &&
+		test_commit initial &&
+		git worktree add -b linked-branch ../wt-linked HEAD &&
+		git worktree add -b prefix-branch ../wt-prefix/linked HEAD
+	) &&
+	wt_main="$(cd wt-multi && pwd)" &&
+	wt_linked="$(cd wt-linked && pwd)" &&
+	wt_prefix_parent="$(cd wt-prefix && pwd)" &&
+	cat >>wt-multi/.git/config <<-EOF &&
+	[includeIf "worktree:$wt_main"]
+		path = main-config
+	[includeIf "worktree:$wt_linked"]
+		path = linked-config
+	[includeIf "worktree:$wt_prefix_parent/"]
+		path = prefix-config
+	EOF
+	echo "[test]mainvar=main" >wt-multi/.git/main-config &&
+	echo "[test]linkedvar=linked" >wt-multi/.git/linked-config &&
+	echo "[test]prefixvar=prefix" >wt-multi/.git/prefix-config &&
+	echo main >expect &&
+	git -C wt-multi config test.mainvar >actual &&
+	test_cmp expect actual &&
+	test_must_fail git -C wt-multi config test.linkedvar &&
+	test_must_fail git -C wt-multi config test.prefixvar &&
+	echo linked >expect &&
+	git -C wt-linked config test.linkedvar >actual &&
+	test_cmp expect actual &&
+	test_must_fail git -C wt-linked config test.mainvar &&
+	test_must_fail git -C wt-linked config test.prefixvar &&
+	echo prefix >expect &&
+	git -C wt-prefix/linked config test.prefixvar >actual &&
+	test_cmp expect actual &&
+	test_must_fail git -C wt-prefix/linked config test.mainvar &&
+	test_must_fail git -C wt-prefix/linked config test.linkedvar
+'
+
+test_expect_success SYMLINKS 'conditional include, worktree resolves symlinks' '
+	mkdir real-wt &&
+	ln -s real-wt link-wt &&
+	git init link-wt/repo &&
+	(
+		cd link-wt/repo &&
+		# repo->worktree resolves symlinks, so use real path in pattern
+		echo "[includeIf \"worktree:**/real-wt/repo\"]path=bar-link" >>.git/config &&
+		echo "[test]wtlink=2" >.git/bar-link &&
+		echo 2 >expect &&
+		git config test.wtlink >actual &&
+		test_cmp expect actual
+	)
+'
+
+test_expect_success 'conditional include, worktree, icase' '
+	git init wt-icase &&
+	(
+		cd wt-icase &&
+		test_commit initial &&
+		wt_path="$(pwd)" &&
+		wt_upper=$(echo "$wt_path" | tr a-z A-Z) &&
+		echo "[includeIf \"worktree/i:$wt_upper\"]path=icase-inc" >>.git/config &&
+		echo "[test]wticase=1" >.git/icase-inc &&
+		echo 1 >expect &&
+		git config test.wticase >actual &&
+		test_cmp expect actual
+	)
+'
+
+# The "worktree" condition cannot match during early config reading
+# because the repository object is not yet fully initialized and
+# repo_get_work_tree() returns NULL.
+test_expect_success 'conditional include, worktree does not match in early config' '
+	git init wt-early &&
+	(
+		cd wt-early &&
+		test_commit initial &&
+		wt_path="$(pwd)" &&
+		echo "[includeIf \"worktree:$wt_path\"]path=early-inc" >>.git/config &&
+		echo "[test]wtearly=1" >.git/early-inc &&
+		test-tool config read_early_config test.wtearly >actual &&
+		test_must_be_empty actual
+	)
+'
+
+test_expect_success 'conditional include, worktree without repository' '
+	test_when_finished "rm -f .gitconfig config.inc" &&
+	git config set -f .gitconfig "includeIf.worktree:/.path" config.inc &&
+	git config set -f config.inc foo.bar baz &&
+	git config get foo.bar &&
+	test_must_fail nongit git config get foo.bar
+'
+
+test_expect_success 'conditional include, worktree without repository but explicit nonexistent Git directory' '
+	test_when_finished "rm -f .gitconfig config.inc" &&
+	git config set -f .gitconfig "includeIf.worktree:/.path" config.inc &&
+	git config set -f config.inc foo.bar baz &&
+	git config get foo.bar &&
+	test_must_fail nongit git --git-dir=nonexistent config get foo.bar
+'
+
 test_done

-- 
2.53.0



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH v4 2/2] config: add "worktree" and "worktree/i" includeIf conditions
  2026-05-13  8:08 ` [PATCH v4 2/2] config: add "worktree" and "worktree/i" includeIf conditions Chen Linxuan via B4 Relay
@ 2026-05-13 13:59   ` Phillip Wood
  0 siblings, 0 replies; 4+ messages in thread
From: Phillip Wood @ 2026-05-13 13:59 UTC (permalink / raw)
  To: me, git
  Cc: Kristoffer Haugsbakk, Junio C Hamano, Patrick Steinhardt,
	Phillip Wood

On 13/05/2026 09:08, Chen Linxuan via B4 Relay wrote:
> From: Chen Linxuan <me@black-desk.cn>
> 
> diff --git a/Documentation/config.adoc b/Documentation/config.adoc
> index 62eebe7c5450..6299b1e3a019 100644
> --- a/Documentation/config.adoc
> +++ b/Documentation/config.adoc
> @@ -146,6 +146,46 @@ 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).
> ++
> +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.

Thanks for expanding the documentation - this looks good to me.

Phillip

> +`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 +284,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
> diff --git a/config.c b/config.c
> index 7d5dae0e8450..6d0c2d0725e4 100644
> --- a/config.c
> +++ b/config.c
> @@ -400,6 +400,12 @@ static int include_condition_is_true(const struct key_value_info *kvi,
>   		return include_by_path(kvi, opts->git_dir, cond, cond_len, 0);
>   	else if (skip_prefix_mem(cond, cond_len, "gitdir/i:", &cond, &cond_len))
>   		return include_by_path(kvi, opts->git_dir, cond, cond_len, 1);
> +	else if (skip_prefix_mem(cond, cond_len, "worktree:", &cond, &cond_len))
> +		return include_by_path(kvi, inc->repo ? repo_get_work_tree(inc->repo) : NULL,
> +				       cond, cond_len, 0);
> +	else if (skip_prefix_mem(cond, cond_len, "worktree/i:", &cond, &cond_len))
> +		return include_by_path(kvi, inc->repo ? repo_get_work_tree(inc->repo) : NULL,
> +				       cond, cond_len, 1);
>   	else if (skip_prefix_mem(cond, cond_len, "onbranch:", &cond, &cond_len))
>   		return include_by_branch(inc, cond, cond_len);
>   	else if (skip_prefix_mem(cond, cond_len, "hasconfig:remote.*.url:", &cond,
> diff --git a/t/t1305-config-include.sh b/t/t1305-config-include.sh
> index 6e51f892f320..07b6fb649cd2 100755
> --- a/t/t1305-config-include.sh
> +++ b/t/t1305-config-include.sh
> @@ -396,4 +396,117 @@ test_expect_success 'onbranch without repository but explicit nonexistent Git di
>   	test_must_fail nongit git --git-dir=nonexistent config get foo.bar
>   '
>   
> +# worktree: conditional include tests
> +
> +test_expect_success 'conditional include, worktree bare repo' '
> +	git init --bare wt-bare &&
> +	(
> +		cd wt-bare &&
> +		echo "[includeIf \"worktree:/\"]path=bar-bare" >>config &&
> +		echo "[test]wtbare=1" >bar-bare &&
> +		test_must_fail git config test.wtbare
> +	)
> +'
> +
> +test_expect_success 'conditional include, worktree multiple worktrees' '
> +	git init wt-multi &&
> +	(
> +		cd wt-multi &&
> +		test_commit initial &&
> +		git worktree add -b linked-branch ../wt-linked HEAD &&
> +		git worktree add -b prefix-branch ../wt-prefix/linked HEAD
> +	) &&
> +	wt_main="$(cd wt-multi && pwd)" &&
> +	wt_linked="$(cd wt-linked && pwd)" &&
> +	wt_prefix_parent="$(cd wt-prefix && pwd)" &&
> +	cat >>wt-multi/.git/config <<-EOF &&
> +	[includeIf "worktree:$wt_main"]
> +		path = main-config
> +	[includeIf "worktree:$wt_linked"]
> +		path = linked-config
> +	[includeIf "worktree:$wt_prefix_parent/"]
> +		path = prefix-config
> +	EOF
> +	echo "[test]mainvar=main" >wt-multi/.git/main-config &&
> +	echo "[test]linkedvar=linked" >wt-multi/.git/linked-config &&
> +	echo "[test]prefixvar=prefix" >wt-multi/.git/prefix-config &&
> +	echo main >expect &&
> +	git -C wt-multi config test.mainvar >actual &&
> +	test_cmp expect actual &&
> +	test_must_fail git -C wt-multi config test.linkedvar &&
> +	test_must_fail git -C wt-multi config test.prefixvar &&
> +	echo linked >expect &&
> +	git -C wt-linked config test.linkedvar >actual &&
> +	test_cmp expect actual &&
> +	test_must_fail git -C wt-linked config test.mainvar &&
> +	test_must_fail git -C wt-linked config test.prefixvar &&
> +	echo prefix >expect &&
> +	git -C wt-prefix/linked config test.prefixvar >actual &&
> +	test_cmp expect actual &&
> +	test_must_fail git -C wt-prefix/linked config test.mainvar &&
> +	test_must_fail git -C wt-prefix/linked config test.linkedvar
> +'
> +
> +test_expect_success SYMLINKS 'conditional include, worktree resolves symlinks' '
> +	mkdir real-wt &&
> +	ln -s real-wt link-wt &&
> +	git init link-wt/repo &&
> +	(
> +		cd link-wt/repo &&
> +		# repo->worktree resolves symlinks, so use real path in pattern
> +		echo "[includeIf \"worktree:**/real-wt/repo\"]path=bar-link" >>.git/config &&
> +		echo "[test]wtlink=2" >.git/bar-link &&
> +		echo 2 >expect &&
> +		git config test.wtlink >actual &&
> +		test_cmp expect actual
> +	)
> +'
> +
> +test_expect_success 'conditional include, worktree, icase' '
> +	git init wt-icase &&
> +	(
> +		cd wt-icase &&
> +		test_commit initial &&
> +		wt_path="$(pwd)" &&
> +		wt_upper=$(echo "$wt_path" | tr a-z A-Z) &&
> +		echo "[includeIf \"worktree/i:$wt_upper\"]path=icase-inc" >>.git/config &&
> +		echo "[test]wticase=1" >.git/icase-inc &&
> +		echo 1 >expect &&
> +		git config test.wticase >actual &&
> +		test_cmp expect actual
> +	)
> +'
> +
> +# The "worktree" condition cannot match during early config reading
> +# because the repository object is not yet fully initialized and
> +# repo_get_work_tree() returns NULL.
> +test_expect_success 'conditional include, worktree does not match in early config' '
> +	git init wt-early &&
> +	(
> +		cd wt-early &&
> +		test_commit initial &&
> +		wt_path="$(pwd)" &&
> +		echo "[includeIf \"worktree:$wt_path\"]path=early-inc" >>.git/config &&
> +		echo "[test]wtearly=1" >.git/early-inc &&
> +		test-tool config read_early_config test.wtearly >actual &&
> +		test_must_be_empty actual
> +	)
> +'
> +
> +test_expect_success 'conditional include, worktree without repository' '
> +	test_when_finished "rm -f .gitconfig config.inc" &&
> +	git config set -f .gitconfig "includeIf.worktree:/.path" config.inc &&
> +	git config set -f config.inc foo.bar baz &&
> +	git config get foo.bar &&
> +	test_must_fail nongit git config get foo.bar
> +'
> +
> +test_expect_success 'conditional include, worktree without repository but explicit nonexistent Git directory' '
> +	test_when_finished "rm -f .gitconfig config.inc" &&
> +	git config set -f .gitconfig "includeIf.worktree:/.path" config.inc &&
> +	git config set -f config.inc foo.bar baz &&
> +	git config get foo.bar &&
> +	test_must_fail nongit git --git-dir=nonexistent config get foo.bar
> +'
> +
>   test_done
> 


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-05-13 13:59 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-13  8:08 [PATCH v4 0/2] includeIf: add "worktree" condition for matching working tree path Chen Linxuan via B4 Relay
2026-05-13  8:08 ` [PATCH v4 1/2] config: refactor include_by_gitdir() into include_by_path() Chen Linxuan via B4 Relay
2026-05-13  8:08 ` [PATCH v4 2/2] config: add "worktree" and "worktree/i" includeIf conditions Chen Linxuan via B4 Relay
2026-05-13 13:59   ` Phillip Wood

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox