From: Isabella Caselli <bellacaselli20@gmail.com>
To: git@vger.kernel.org
Cc: Junio C Hamano <gitster@pobox.com>, Jeff King <peff@peff.net>,
Eric Sunshine <sunshine@sunshineco.com>,
Ignacio Encinas <ignacio@iencinas.com>,
Isabella Caselli <bellacaselli20@gmail.com>
Subject: [PATCH 3/3] config: learn the "hostname:" includeIf condition
Date: Sun, 11 Oct 2026 22:58:46 -0300 [thread overview]
Message-ID: <20261012015846.2649843-4-bellacaselli20@gmail.com> (raw)
In-Reply-To: <20261012015846.2649843-1-bellacaselli20@gmail.com>
When the same home directory is shared across multiple machines, they
all read the same ~/.gitconfig. Settings that should differ between
machines therefore need a way to make that file behave differently
on each host. The same problem affects people who keep their dotfiles
in a repository and check them out on multiple machines.
Add a "hostname:" keyword to includeIf. The value that follows is a
pattern supporting standard glob wildcards, and the condition is met
when the machine's hostname matches it. If the hostname cannot be
determined, the condition is not met.
Depending on the system configuration, the hostname may be either a
short name or a fully qualified domain name. Making the name fully
qualified ourselves was considered, but it could require a DNS lookup
while reading the configuration. Instead, match the name as the
system reports it, document this, and point to "git var GIT_HOSTNAME"
as a way to check the value being matched.
The tests obtain the hostname with "git var GIT_HOSTNAME" before
writing the configuration, so that a failure to retrieve it makes
the test fail instead of going unnoticed inside the here-document.
Based-on-patch-by: Ignacio Encinas <ignacio@iencinas.com>
Signed-off-by: Isabella Caselli <bellacaselli20@gmail.com>
---
Documentation/config.adoc | 14 ++++++++++++
Documentation/git-var.adoc | 2 ++
config.c | 17 +++++++++++++++
t/t1305-config-include.sh | 44 ++++++++++++++++++++++++++++++++++++++
4 files changed, 77 insertions(+)
diff --git a/Documentation/config.adoc b/Documentation/config.adoc
index f67dcd2f8e..aa6360e230 100644
--- a/Documentation/config.adoc
+++ b/Documentation/config.adoc
@@ -232,6 +232,16 @@ As for the naming of this keyword, it is for forwards compatibility with
a naming scheme that supports more variable-based include conditions,
but currently Git only supports the exact keyword described above.
+`hostname`::
+ The data that follows the keyword `hostname:` is taken to be a
+ pattern with standard globbing wildcards. If the hostname of
+ the machine matches the pattern, the include condition is met.
++
+Depending on how your system is configured, the hostname used for
+matching may be short (e.g., "myhost") or a fully qualified domain
+name ("myhost.example.com"). Run `git var GIT_HOSTNAME` to see the
+hostname Git uses (see linkgit:git-var[1]).
+
A few more notes on matching via `gitdir` and `gitdir/i`:
* Symlinks in `$GIT_DIR` are not resolved before matching.
@@ -315,6 +325,10 @@ Example
path = foo.inc
[remote "origin"]
url = https://example.com/git
+
+; include only if the hostname of the machine matches some-hostname
+[includeIf "hostname:some-hostname"]
+ path = foo.inc
----
Values
diff --git a/Documentation/git-var.adoc b/Documentation/git-var.adoc
index e813ab4fd2..fc2def16d3 100644
--- a/Documentation/git-var.adoc
+++ b/Documentation/git-var.adoc
@@ -86,6 +86,8 @@ endif::git-default-pager[]
`GIT_HOSTNAME`::
The hostname of the machine, as reported by the operating system.
+ This is the hostname matched by `includeIf "hostname:..."` (see
+ linkgit:git-config[1]).
Most path values contain only one value. However, some can contain multiple
values, which are separated by newlines, and are listed in order from highest to
diff --git a/config.c b/config.c
index e0bb29b53d..c891f63e60 100644
--- a/config.c
+++ b/config.c
@@ -316,6 +316,21 @@ static int include_by_branch(struct config_include_data *data,
return ret;
}
+static int include_by_hostname(const char *cond, size_t cond_len)
+{
+ int ret;
+ char my_host[HOST_NAME_MAX + 1];
+ char *pattern;
+
+ if (xgethostname(my_host, sizeof(my_host)))
+ return 0;
+
+ pattern = xmemdupz(cond, cond_len);
+ ret = !wildmatch(pattern, my_host, 0);
+ free(pattern);
+ return ret;
+}
+
static int add_remote_url(const char *var, const char *value,
const struct config_context *ctx UNUSED, void *data)
{
@@ -411,6 +426,8 @@ static int include_condition_is_true(const struct key_value_info *kvi,
else if (skip_prefix_mem(cond, cond_len, "hasconfig:remote.*.url:", &cond,
&cond_len))
return include_by_remote_url(inc, cond, cond_len);
+ else if (skip_prefix_mem(cond, cond_len, "hostname:", &cond, &cond_len))
+ return include_by_hostname(cond, cond_len);
/* unknown conditionals are always false */
return 0;
diff --git a/t/t1305-config-include.sh b/t/t1305-config-include.sh
index 507b8ebd06..01069237ba 100755
--- a/t/t1305-config-include.sh
+++ b/t/t1305-config-include.sh
@@ -524,4 +524,48 @@ test_expect_success 'conditional include, worktree without repository but explic
test_must_fail nongit git --git-dir=nonexistent config get foo.bar
'
+test_expect_success 'conditional include, hostname' '
+ hostname=$(git var GIT_HOSTNAME) &&
+ cat >>.git/config <<-EOF &&
+ [includeIf "hostname:${hostname}a"]
+ path = bar12
+ EOF
+ cat >>.git/bar12 <<-EOF &&
+ [test]
+ twelve=12
+ EOF
+
+ test_must_fail git config test.twelve &&
+
+ cat >>.git/config <<-EOF &&
+ [includeIf "hostname:$hostname"]
+ path = bar12
+ EOF
+ echo 12 >expect &&
+ git config test.twelve >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'conditional include, hostname, wildcard' '
+ hostname=$(git var GIT_HOSTNAME) &&
+ cat >>.git/config <<-EOF &&
+ [includeIf "hostname:${hostname}a*"]
+ path = bar13
+ EOF
+ cat >>.git/bar13 <<-EOF &&
+ [test]
+ thirteen = 13
+ EOF
+
+ test_must_fail git config test.thirteen &&
+
+ cat >>.git/config <<-EOF &&
+ [includeIf "hostname:$hostname*"]
+ path = bar13
+ EOF
+ echo 13 >expect &&
+ git config test.thirteen >actual &&
+ test_cmp expect actual
+'
+
test_done
--
2.43.0
next prev parent reply other threads:[~2026-10-12 2:03 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-28 23:43 hostname: includeIf condition — anyone already working on this? Isabella Caselli
2026-09-29 1:44 ` Jeff King
2026-09-29 12:14 ` Ignacio Encinas
2026-09-29 18:28 ` Jeff King
2026-09-29 19:55 ` Junio C Hamano
2026-10-02 1:52 ` Isabella Caselli
2026-10-12 1:58 ` [PATCH 0/3] Add hostname condition to includeIf Isabella Caselli
2026-10-12 1:58 ` [PATCH 1/3] var: add GIT_HOSTNAME Isabella Caselli
2026-10-12 1:58 ` [PATCH 2/3] t6500: get hostname from "git var" Isabella Caselli
2026-10-12 19:20 ` Junio C Hamano
2026-10-13 1:14 ` Isabella Caselli
2026-10-13 1:43 ` Junio C Hamano
2026-10-12 1:58 ` Isabella Caselli [this message]
2026-10-12 19:24 ` [PATCH 3/3] config: learn the "hostname:" includeIf condition Junio C Hamano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261012015846.2649843-4-bellacaselli20@gmail.com \
--to=bellacaselli20@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=ignacio@iencinas.com \
--cc=peff@peff.net \
--cc=sunshine@sunshineco.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox