git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [RFC] Support UTF-8 characters in Git alias names

From
Jeff King <peff@peff.net>
Date
Feb 9, 2026, 07:36 UTC
Message-ID
<20260209073602.GC585828@coredump.intra.peff.net>
In-Reply-To
<3124b359-2929-4f3f-9ac6-793277fe422b@jontes.page>
On Sun, Feb 08, 2026 at 04:30:02PM +0100, Jonatan Holmgren wrote:
Show 14 quoted lines
> I think the best approach is to support UTF-8 specifically for alias.*
> variables, which would mean modifying the git_config_parse_key() fn to allow
> UTF-8 bytes and make non-ascii aliases case-sensitive to avoid complex
> locale-dependent case folding.
> 
> The main pain point would be making sure all platforms handle this nicely,
> esp since mac uses NFD and not NFC Unicode.
> 
> Before implementing this, I'd like to hear:
> 
> 1. Is this a feature the project would like?
> 2. Is my implementation approach reasonable?
> 3. What concerns should be addressed in said design?
> 4. Any compat requirements I should be aware of?
I think supporting non-ascii aliases is a good goal.

However, I'm not sure that special-casing the parsing of alias config keys is the best direction. Since it's a syntactic change, the special case would have to be understand by all code that reads or writes config, not just git_config_parse_key(). And then you'd potentially run into problems with older versions of Git, or alternate implementations (of which there are several).

Plus it doesn't solve all of the issues. E.g., should we allow new characters like "_" (for a potential "git foo_bar")? That is doable, but what about "." (for "git foo.bar")? I think that introduces new ambiguities into the syntax.

Taking a step back, I think the root of the issue is that the schema for alias keys is poorly designed. Git's config syntax allows for three levels: section, subsection, and key. The section and key fields are restricted to alnum and dash, but the subsection is designed to be unrestricted (modulo NUL bytes).

And that's why we have:
  [branch "foo/bar"]
  remote = origin

for example, because branch names don't follow the same syntax rules as config keys. And it's the same issue here: the alias.* schema is trying to use one syntax (alnum config keys) to store another (command names). They _usually_ overlap, but not always. The pager.* config has the same problem.

We've discussed this before, e.g., in:
  https://lore.kernel.org/git/20150206124528.GA18859@inner.h.apk.li/

There the immediate problem was that "git foo_bar" caused an error message. We hacked around it by suppressing the error, but it was still impossible to add an alias or pager config. We knew that was a limitation, but punted until somebody came along who actually cared about making it work. Now you get to be that somebody. ;)

So what I'd propose instead is introducing a new schema like:
  - setting "alias.foo.command" to "bar" would alias "git foo" to "bar";
    this should work for any command name, as it is just a byte stream
  - a given command subsection is matched verbatim. So alias.foo.command
    matches "git foo" but not "git Foo". Likewise, we do not do any
    normalization. You put what you want into your config, and it should
    match the command you invoke. This is perhaps less friendly, but it
    punts on any normalization or case-folding that we have to do, and
    matches how the rest of Git works (paths are likewise streams of
    bytes, and it is mostly up to the user to use them consistently).
  - leave "alias.foo" as a historical synonym for "alias.foo.command",
    so that existing config continues working
  - optionally add new keys within alias.foo.* sections. For example, we
    could allow alias.foo.help to provide text shown during "git help
    foo". For the most part that could come later, so I'm just
    illustrating possible eventual directions that the new schema would
    allow. But it might be worth pondering a little now to avoid
    painting ourselves into a corner. E.g., you could imagine a schema
    where alias.foo.shell is set to "true" instead of sticking a "!" at
    the front of the value of alias.foo.command. I don't know if that's
    a good idea or not, but if we were going to do stuff like that, we'd
    want to decide now before setting the alias.foo.command behavior in
    stone.
  - likewise, optionally do the same for pager.*

I hacked together some illustrative code below. Note that we do use strcasecmp() currently to match command names (which kind of makes sense, since if you had "alias.Foo" in your config, the parser would downcase it to "alias.foo"). So probably that historical code should continue to behave like that, but the new "alias.Foo.command" should be more verbatim (the patch below just feeds them both to strcasecmp).

-Peff
---
diff --git a/alias.c b/alias.c
index 1a1a141a0a..44bdde58af 100644
--- a/alias.c
+++ b/alias.c
@@ -17,19 +17,30 @@ 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, *p;
+	size_t cmd_len;
 
-	if (!skip_prefix(key, "alias.", &p))
+	if (parse_config_key(key, "alias", &cmd, &cmd_len, &p) < 0)
 		return 0;
 
+	if (cmd) {
+		/* The only 3-level key we understand is alias.*.command */
+		if (strcmp(p, "command"))
+			return 0;
+	} else {
+		/* alias.foo is the same as alias.foo.command */
+		cmd = p;
+		cmd_len = strlen(p);
+	}
+
 	if (data->alias) {
-		if (!strcasecmp(p, data->alias)) {
+		if (!strncasecmp(cmd, data->alias, cmd_len)) {
 			FREE_AND_NULL(data->v);
 			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;
Previous: Jeff KingNext: Theodore Tso
Message 12 of 88 in “[RFC] Support UTF-8 characters in Git alias names”
  1. Jonatan HolmgrenFeb 8, 2026
  2. D. Ben KnobleFeb 8, 2026
  3. brian m. carlsonFeb 8, 2026
  4. Junio C HamanoFeb 9, 2026
  5. Jonatan HolmgrenFeb 9, 2026
  6. Junio C HamanoFeb 9, 2026
  7. brian m. carlsonFeb 9, 2026
  8. Junio C HamanoFeb 9, 2026
  9. Ben KnobleFeb 10, 2026
  10. Junio C HamanoFeb 10, 2026
  11. Jeff KingFeb 10, 2026
  12. Jeff KingFeb 9, 2026
  13. Theodore TsoFeb 9, 2026
  14. alias: support UTF-8 characters via subsection syntaxJonatan Holmgren, Feb 9, 2026
  15. Jeff KingFeb 10, 2026
  16. Torsten BögershausenFeb 10, 2026
  17. Junio C HamanoFeb 10, 2026
  18. 0/2 support UTF-8 in alias namesJonatan Holmgren, Feb 10, 2026
  19. 1/2 help: use list_aliases() for alias listing and lookupJonatan Holmgren, Feb 10, 2026
  20. Junio C HamanoFeb 10, 2026
  21. 2/2 alias: support non-alphanumeric names via subsection syntaxJonatan Holmgren, Feb 10, 2026
  22. Junio C HamanoFeb 10, 2026
  23. Jonatan HolmgrenFeb 10, 2026
  24. Kristoffer HaugsbakkFeb 23, 2026
  25. Kristoffer HaugsbakkFeb 23, 2026
  26. Junio C HamanoFeb 23, 2026
  27. Kristoffer HaugsbakkFeb 23, 2026
  28. Patrick SteinhardtFeb 24, 2026
  29. 0/3 support UTF-8 in alias namesJonatan Holmgren, Feb 10, 2026
  30. 1/3 help: use list_aliases() for alias listingJonatan Holmgren, Feb 10, 2026
  31. Junio C HamanoFeb 10, 2026
  32. 2/3 alias: prepare for subsection aliasesJonatan Holmgren, Feb 10, 2026
  33. 3/3 alias: support non-alphanumeric names via subsection syntaxJonatan Holmgren, Feb 10, 2026
  34. 0/3 support UTF-8 in alias namesJonatan Holmgren, Feb 11, 2026
  35. 2/3 alias: prepare for subsection aliasesJonatan Holmgren, Feb 11, 2026
  36. Junio C HamanoFeb 11, 2026
  37. 1/3 help: use list_aliases() for alias listingJonatan Holmgren, Feb 11, 2026
  38. Junio C HamanoFeb 11, 2026
  39. 3/3 alias: support non-alphanumeric names via subsection syntaxJonatan Holmgren, Feb 11, 2026
  40. Junio C HamanoFeb 11, 2026
  41. Richard KerryFeb 12, 2026
  42. Jonatan HolmgrenFeb 12, 2026
  43. Jonatan HolmgrenFeb 12, 2026
  44. Torsten BögershausenFeb 12, 2026
  45. Jonatan HolmgrenFeb 12, 2026
  46. 0/4 support uTF-8 in alias namesJonatan Holmgren, Feb 16, 2026
  47. 4/4 completion: fix zsh alias listing for subsection aliasesJonatan Holmgren, Feb 16, 2026
  48. D. Ben KnobleFeb 16, 2026
  49. Junio C HamanoFeb 17, 2026
  50. 2/4 alias: prepare for subsection aliasesJonatan Holmgren, Feb 16, 2026
  51. 1/4 help: use list_aliases() for alias listingJonatan Holmgren, Feb 16, 2026
  52. 3/4 alias: support non-alphanumeric names via subsection syntaxJonatan Holmgren, Feb 16, 2026
  53. 0/4 support UTF-8 in alias namesJonatan Holmgren, Feb 18, 2026
  54. 2/4 alias: prepare for subsection aliasesJonatan Holmgren, Feb 18, 2026
  55. Kristoffer HaugsbakkFeb 18, 2026
  56. 1/4 help: use list_aliases() for alias listingJonatan Holmgren, Feb 18, 2026
  57. 4/4 completion: fix zsh alias listing for subsection aliasesJonatan Holmgren, Feb 18, 2026
  58. 3/4 alias: support non-alphanumeric names via subsection syntaxJonatan Holmgren, Feb 18, 2026
  59. 0/4 support UTF-8 in alias namesJonatan Holmgren, Feb 18, 2026
  60. 1/4 help: use list_aliases() for alias listingJonatan Holmgren, Feb 18, 2026
  61. Jacob KellerFeb 24, 2026
  62. Junio C HamanoFeb 24, 2026
  63. Junio C HamanoFeb 25, 2026
  64. Jacob KellerFeb 26, 2026
  65. Jacob KellerFeb 24, 2026
  66. 2/4 alias: prepare for subsection aliasesJonatan Holmgren, Feb 18, 2026
  67. 3/4 alias: support non-alphanumeric names via subsection syntaxJonatan Holmgren, Feb 18, 2026
  68. Kristoffer HaugsbakkFeb 24, 2026
  69. Jonatan HolmgrenFeb 24, 2026
  70. Kristoffer HaugsbakkFeb 24, 2026
  71. 4/4 completion: fix zsh alias listing for subsection aliasesJonatan Holmgren, Feb 18, 2026
  72. Junio C HamanoFeb 19, 2026
  73. Jonatan HolmgrenFeb 19, 2026
  74. 0/2 Fix small issues in alias subsection handlingJonatan Holmgren, Feb 24, 2026
  75. 1/2 doc: fix list continuation in alias subsection exampleJonatan Holmgren, Feb 24, 2026
  76. Junio C HamanoFeb 24, 2026
  77. Kristoffer HaugsbakkFeb 24, 2026
  78. Junio C HamanoFeb 24, 2026
  79. 2/2 alias: treat empty subsection [alias ""] as plain [alias]Jonatan Holmgren, Feb 24, 2026
  80. Junio C HamanoFeb 26, 2026
  81. 0/3 Fix small issues in alias subsection handlingJonatan Holmgren, Feb 26, 2026
  82. 2/3 alias: treat empty subsection [alias ""] as plain [alias]Jonatan Holmgren, Feb 26, 2026
  83. 1/3 doc: fix list continuation in alias subsection exampleJonatan Holmgren, Feb 26, 2026
  84. Kristoffer HaugsbakkMar 3, 2026
  85. Jonatan HolmgrenMar 3, 2026
  86. 3/3 git, help: fix memory leaks in alias listingJonatan Holmgren, Feb 26, 2026
  87. Junio C HamanoFeb 26, 2026
  88. doc: fix list continuation in alias.adocJonatan Holmgren, Mar 3, 2026

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.