From: Jonatan Holmgren <jonatan@jontes•page>
To: git@vger•kernel.org
Cc: peff@peff•net, gitster@pobox•com,
"D . Ben Knoble" <benknoble@gmail•com>,
"brian m . carlson" <sandals@crustytoothpaste•net>,
Jonatan Holmgren <jonatan@jontes•page>
Subject: [PATCH v1] alias: support UTF-8 characters via subsection syntax
Date: Mon, 9 Feb 2026 23:01:15 +0100 [thread overview]
Message-ID: <20260209220115.461109-1-jonatan@jontes.page> (raw)
In-Reply-To: <3124b359-2929-4f3f-9ac6-793277fe422b@jontes.page>
Git aliases are currently restricted to ASCII characters due to
config key syntax limitations. This prevents non-English speakers
from creating aliases in their native languages.
Add support for UTF-8 alias names using config subsections:
[alias "förgrena"]
command = branch
The subsection name is matched verbatim (case-sensitive), while the
existing flat syntax (alias.name) remains case-insensitive for
backward compatibility. This approach uses existing config
infrastructure and avoids complex Unicode normalization.
Suggested-by: Jeff King <peff@peff•net>
Signed-off-by: Jonatan Holmgren <jonatan@jontes•page>
---
Documentation/RelNotes/2.54.0.adoc | 8 +++++
Documentation/config/alias.adoc | 53 +++++++++++++++++++++++++-----
alias.c | 38 +++++++++++++++++----
t/t0014-alias-utf8.sh | 44 +++++++++++++++++++++++++
t/t0014-alias.sh | 32 ++++++++++++++++++
5 files changed, 161 insertions(+), 14 deletions(-)
create mode 100755 t/t0014-alias-utf8.sh
diff --git a/Documentation/RelNotes/2.54.0.adoc b/Documentation/RelNotes/2.54.0.adoc
index 20c660d82a..8cb00a21bb 100644
--- a/Documentation/RelNotes/2.54.0.adoc
+++ b/Documentation/RelNotes/2.54.0.adoc
@@ -7,6 +7,14 @@ UI, Workflows & Features
* "git add -p" and friends note what the current status of the hunk
being shown is.
+ * Git aliases now support UTF-8 characters in alias names through
+ subsection syntax: `[alias "name"] command = value`. This enables
+ aliases in non-English languages. The flat syntax continues
+ to work for backward compatibility.
+
+ * The new subsection syntax uses case-sensitive matching and
+ the flat syntax remains case-insensitive for backward compatibility.
+
Performance, Internal Implementation, Development Support etc.
--------------------------------------------------------------
diff --git a/Documentation/config/alias.adoc b/Documentation/config/alias.adoc
index 80ce17d2de..feba1e2022 100644
--- a/Documentation/config/alias.adoc
+++ b/Documentation/config/alias.adoc
@@ -1,12 +1,49 @@
alias.*::
- Command aliases for the linkgit:git[1] command wrapper - e.g.
- after defining `alias.last = cat-file commit HEAD`, the invocation
- `git last` is equivalent to `git cat-file commit HEAD`. To avoid
- confusion and troubles with script usage, aliases that
- hide existing Git commands are ignored except for deprecated
- commands. Arguments are split by
- spaces, the usual shell quoting and escaping are supported.
- A quote pair or a backslash can be used to quote them.
+alias.*.command::
+ Command aliases for the linkgit:git[1] command wrapper. Aliases
+ can be defined using two syntaxes:
++
+--
+1. **Simple syntax** (case-insensitive): `alias.name = value`
+2. **Subsection syntax** (recommended for UTF-8/special characters):
+ `[alias "name"]` with `command = value`
+
+The subsection syntax allows alias names containing UTF-8 characters,
+spaces, or special characters, as the subsection preserves the exact
+bytes including case.
+--
++
+Examples:
++
+----
+# Simple syntax (ASCII names)
+[alias]
+ co = checkout
+ st = status
+
+# Subsection syntax (UTF-8 and special characters)
+[alias "hämta"]
+ command = fetch
+[alias "gömma"]
+ command = stash
+[alias "my alias with whitespace"]
+ command = "status --short"
+----
++
+After defining these, you can run `git co`, `git hämta`, `git gömma`,
+and `git "my alias with whitespace"` (note the quotes for aliases with spaces).
++
+**Note:** The flat syntax `alias.name` remains case-insensitive for
+backward compatibility. The new subsection syntax is case-sensitive:
+`[alias "Foo"]` and `[alias "foo"]` are different aliases.
++
+E.g. after defining `alias.last = cat-file commit HEAD`, the invocation
+`git last` is equivalent to `git cat-file commit HEAD`. To avoid
+confusion and troubles with script usage, aliases that
+hide existing Git commands are ignored except for deprecated
+commands. Arguments are split by
+spaces, the usual shell quoting and escaping are supported.
+A quote pair or a backslash can be used to quote them.
+
Note that the first word of an alias does not necessarily have to be a
command. It can be a command-line option that will be passed into the
diff --git a/alias.c b/alias.c
index 1a1a141a0a..f0c5f12fdd 100644
--- a/alias.c
+++ b/alias.c
@@ -17,19 +17,45 @@ static int config_alias_cb(const char *key, const char *value,
const struct config_context *ctx UNUSED, void *d)
{
struct config_alias_data *data = d;
- const char *p;
+ const char *cmd, *subkey;
+ size_t cmd_len;
+ int is_subsection;
- if (!skip_prefix(key, "alias.", &p))
+ /* Use parse_config_key() to handle both 2-level and 3-level keys */
+ if (parse_config_key(key, "alias", &cmd, &cmd_len, &subkey) < 0)
return 0;
+ /*
+ * Support two syntaxes:
+ * 1. alias.name = value (simple, 2-level key)
+ * 2. [alias "name"] command = value (new, 3-level key)
+ */
+ if (cmd) {
+ if (strcmp(subkey, "command"))
+ return 0;
+ is_subsection = 1;
+ } else {
+ cmd = subkey;
+ cmd_len = strlen(cmd);
+ is_subsection = 0;
+ }
+
if (data->alias) {
- if (!strcasecmp(p, data->alias)) {
+ int match;
+ if (is_subsection) {
+ match = (strlen(data->alias) == cmd_len &&
+ !strncmp(data->alias, cmd, cmd_len));
+ } else {
+ match = (strlen(data->alias) == cmd_len &&
+ !strncasecmp(data->alias, cmd, cmd_len));
+ }
+
+ if (match) {
FREE_AND_NULL(data->v);
- return git_config_string(&data->v,
- key, value);
+ return git_config_string(&data->v, key, value);
}
} else if (data->list) {
- string_list_append(data->list, p);
+ string_list_append_nodup(data->list, xmemdupz(cmd, cmd_len));
}
return 0;
diff --git a/t/t0014-alias-utf8.sh b/t/t0014-alias-utf8.sh
new file mode 100755
index 0000000000..d55b5a7213
--- /dev/null
+++ b/t/t0014-alias-utf8.sh
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+test_description='UTF-8 support in git aliases via subsection syntax'
+
+. ./test-lib.sh
+
+# Skip if filesystem/locale doesn't support UTF-8
+test_lazy_prereq UTF8_LOCALE '
+ test_have_prereq !MINGW &&
+ test_set_prereq UTF8_LOCALE
+'
+
+test_expect_success 'setup test repository' '
+ git init &&
+ test_commit initial
+'
+
+test_expect_success UTF8_LOCALE 'setup UTF-8 aliases' '
+ git config alias."förgrena".command branch &&
+ git config alias."分支".command "branch --list" &&
+ git config alias."test name".command status
+'
+
+test_expect_success UTF8_LOCALE 'UTF-8 alias with Swedish characters' '
+ git förgrena >output &&
+ test_grep -E "^(\* )?(main|master)" output
+'
+
+test_expect_success UTF8_LOCALE 'UTF-8 alias with CJK characters' '
+ git 分支 >output &&
+ test_grep -E "^(\* )?(main|master)" output
+'
+
+test_expect_success UTF8_LOCALE 'alias with spaces in name' '
+ git "test name" >output &&
+ test_grep "On branch" output
+'
+
+test_expect_success 'list UTF-8 aliases' '
+ git config --get-regexp "^alias\\..*\\.command" >output &&
+ test_line_count -ge 3 output
+'
+
+test_done
diff --git a/t/t0014-alias.sh b/t/t0014-alias.sh
index 07a53e7366..b19a8a5061 100755
--- a/t/t0014-alias.sh
+++ b/t/t0014-alias.sh
@@ -111,5 +111,37 @@ test_expect_success 'cannot alias-shadow a sample of regular builtins' '
cannot_alias_regular_builtin "$cmd" || return 1
done
'
+test_expect_success 'flat syntax still works' '
+ git config alias.testlegacy status &&
+ git testlegacy >output &&
+ test_grep "On branch" output
+'
+
+test_expect_success 'new subsection syntax works' '
+ git config alias.testnew.command status &&
+ git testnew >output &&
+ test_grep "On branch" output
+'
+
+test_expect_success 'subsection syntax only accepts command key' '
+ git config alias.invalid.notcommand "value" &&
+ test_must_fail git invalid 2>error &&
+ test_grep -i "not a git command" error
+'
+
+test_expect_success 'simple syntax is case-insensitive' '
+ git config alias.LegacyCase status &&
+ git legacycase >output 2>&1 &&
+ test_grep "On branch" output
+'
+
+test_expect_success 'subsection syntax is case-sensitive' '
+ test_commit case-test &&
+ git config alias.SubCase.command "log --oneline" &&
+ git config alias.subcase.command status &&
+ git SubCase >upper.out 2>&1 &&
+ git subcase >lower.out 2>&1 &&
+ ! test_cmp upper.out lower.out
+'
test_done
--
2.53.0
next prev parent reply other threads:[~2026-02-09 22:02 UTC|newest]
Thread overview: 88+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-08 15:30 [RFC] Support UTF-8 characters in Git alias names Jonatan Holmgren
2026-02-08 16:07 ` D. Ben Knoble
2026-02-08 23:21 ` brian m. carlson
2026-02-09 14:55 ` Junio C Hamano
2026-02-09 15:19 ` Jonatan Holmgren
2026-02-09 17:59 ` Junio C Hamano
2026-02-09 22:40 ` brian m. carlson
2026-02-09 23:14 ` Junio C Hamano
2026-02-10 0:45 ` Ben Knoble
2026-02-10 1:04 ` Junio C Hamano
2026-02-10 6:59 ` Jeff King
2026-02-09 7:36 ` Jeff King
2026-02-09 13:59 ` Theodore Tso
2026-02-09 22:01 ` Jonatan Holmgren [this message]
2026-02-10 7:44 ` [PATCH v1] alias: support UTF-8 characters via subsection syntax Jeff King
2026-02-10 8:30 ` Torsten Bögershausen
2026-02-10 16:35 ` Junio C Hamano
2026-02-10 18:31 ` [PATCH v2 0/2] support UTF-8 in alias names Jonatan Holmgren
2026-02-10 18:31 ` [PATCH v2 1/2] help: use list_aliases() for alias listing and lookup Jonatan Holmgren
2026-02-10 19:27 ` Junio C Hamano
2026-02-10 18:31 ` [PATCH v2 2/2] alias: support non-alphanumeric names via subsection syntax Jonatan Holmgren
2026-02-10 19:47 ` Junio C Hamano
2026-02-10 22:29 ` Jonatan Holmgren
2026-02-23 9:29 ` Kristoffer Haugsbakk
2026-02-23 16:07 ` Kristoffer Haugsbakk
2026-02-23 20:22 ` Junio C Hamano
2026-02-23 20:25 ` Kristoffer Haugsbakk
2026-02-24 10:27 ` Patrick Steinhardt
2026-02-10 22:27 ` [PATCH 0/3] support UTF-8 in alias names Jonatan Holmgren
2026-02-10 22:27 ` [PATCH 1/3] help: use list_aliases() for alias listing Jonatan Holmgren
2026-02-10 23:17 ` Junio C Hamano
2026-02-10 22:27 ` [PATCH 2/3] alias: prepare for subsection aliases Jonatan Holmgren
2026-02-10 22:27 ` [PATCH 3/3] alias: support non-alphanumeric names via subsection syntax Jonatan Holmgren
2026-02-11 21:18 ` [PATCH v4 0/3] support UTF-8 in alias names Jonatan Holmgren
2026-02-11 21:18 ` [PATCH v4 1/3] help: use list_aliases() for alias listing Jonatan Holmgren
2026-02-11 22:29 ` Junio C Hamano
2026-02-11 21:18 ` [PATCH v4 2/3] alias: prepare for subsection aliases Jonatan Holmgren
2026-02-11 21:53 ` Junio C Hamano
2026-02-11 21:18 ` [PATCH v4 3/3] alias: support non-alphanumeric names via subsection syntax Jonatan Holmgren
2026-02-11 22:28 ` Junio C Hamano
2026-02-12 11:16 ` Richard Kerry
2026-02-12 15:34 ` Jonatan Holmgren
2026-02-12 18:52 ` Jonatan Holmgren
2026-02-12 10:27 ` [PATCH v4 0/3] support UTF-8 in alias names Torsten Bögershausen
2026-02-12 15:35 ` Jonatan Holmgren
2026-02-16 16:15 ` [PATCH v5 0/4] support uTF-8 " Jonatan Holmgren
2026-02-16 16:15 ` [PATCH v5 1/4] help: use list_aliases() for alias listing Jonatan Holmgren
2026-02-16 16:15 ` [PATCH v5 2/4] alias: prepare for subsection aliases Jonatan Holmgren
2026-02-16 16:15 ` [PATCH v5 3/4] alias: support non-alphanumeric names via subsection syntax Jonatan Holmgren
2026-02-16 16:15 ` [PATCH v5 4/4] completion: fix zsh alias listing for subsection aliases Jonatan Holmgren
2026-02-16 18:32 ` D. Ben Knoble
2026-02-17 20:01 ` Junio C Hamano
2026-02-18 14:52 ` [PATCH v6 0/4] support UTF-8 in alias names Jonatan Holmgren
2026-02-18 14:52 ` [PATCH v6 1/4] help: use list_aliases() for alias listing Jonatan Holmgren
2026-02-18 14:52 ` [PATCH v6 2/4] alias: prepare for subsection aliases Jonatan Holmgren
2026-02-18 16:21 ` Kristoffer Haugsbakk
2026-02-18 14:52 ` [PATCH v6 3/4] alias: support non-alphanumeric names via subsection syntax Jonatan Holmgren
2026-02-18 14:52 ` [PATCH v6 4/4] completion: fix zsh alias listing for subsection aliases Jonatan Holmgren
2026-02-18 21:57 ` [PATCH v7 0/4] support UTF-8 in alias names Jonatan Holmgren
2026-02-18 21:57 ` [PATCH v7 1/4] help: use list_aliases() for alias listing Jonatan Holmgren
2026-02-24 22:19 ` Jacob Keller
2026-02-24 22:41 ` Junio C Hamano
2026-02-25 20:45 ` Junio C Hamano
2026-02-26 23:33 ` Jacob Keller
2026-02-24 22:21 ` Jacob Keller
2026-02-18 21:57 ` [PATCH v7 2/4] alias: prepare for subsection aliases Jonatan Holmgren
2026-02-18 21:57 ` [PATCH v7 3/4] alias: support non-alphanumeric names via subsection syntax Jonatan Holmgren
2026-02-24 10:55 ` Kristoffer Haugsbakk
2026-02-24 14:48 ` Jonatan Holmgren
2026-02-24 23:23 ` Kristoffer Haugsbakk
2026-02-18 21:57 ` [PATCH v7 4/4] completion: fix zsh alias listing for subsection aliases Jonatan Holmgren
2026-02-19 18:17 ` [PATCH v7 0/4] support UTF-8 in alias names Junio C Hamano
2026-02-19 18:54 ` Jonatan Holmgren
2026-02-24 17:12 ` [PATCH 0/2] Fix small issues in alias subsection handling Jonatan Holmgren
2026-02-24 17:12 ` [PATCH 1/2] doc: fix list continuation in alias subsection example Jonatan Holmgren
2026-02-24 19:11 ` Junio C Hamano
2026-02-24 19:14 ` Kristoffer Haugsbakk
2026-02-24 20:23 ` Junio C Hamano
2026-02-24 17:12 ` [PATCH 2/2] alias: treat empty subsection [alias ""] as plain [alias] Jonatan Holmgren
2026-02-26 17:00 ` [PATCH 0/2] Fix small issues in alias subsection handling Junio C Hamano
2026-02-26 20:53 ` [PATCH v2 0/3] " Jonatan Holmgren
2026-02-26 20:53 ` [PATCH v2 1/3] doc: fix list continuation in alias subsection example Jonatan Holmgren
2026-03-03 9:41 ` Kristoffer Haugsbakk
2026-03-03 15:13 ` [PATCH v2 1/3] doc: fix list continuation in alias subsection example! Jonatan Holmgren
2026-02-26 20:53 ` [PATCH v2 2/3] alias: treat empty subsection [alias ""] as plain [alias] Jonatan Holmgren
2026-02-26 20:53 ` [PATCH v2 3/3] git, help: fix memory leaks in alias listing Jonatan Holmgren
2026-02-26 21:08 ` [PATCH v2 0/3] Fix small issues in alias subsection handling Junio C Hamano
2026-03-03 15:12 ` [PATCH] doc: fix list continuation in alias.adoc Jonatan Holmgren
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=20260209220115.461109-1-jonatan@jontes.page \
--to=jonatan@jontes$(echo .)page \
--cc=benknoble@gmail$(echo .)com \
--cc=git@vger$(echo .)kernel.org \
--cc=gitster@pobox$(echo .)com \
--cc=peff@peff$(echo .)net \
--cc=sandals@crustytoothpaste$(echo .)net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
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