Sorry for not responding quickly. Thank you for the patch, but it seems the problem still remains. Although % git ls-files NFD (apparently) works, % git ls-files NFC still gives the error (if core.precomposeunicode is not set in global config). The following is some info I got (hope it is correct and useful), but I have no idea how to fix the problem. precompose_string_if_needed() works only if: precomposed_unicode is already set to 1, or git_config_get_bool("core.precomposeunicode") sets it to 1. But git_config_get_bool() reads the file .git/config only if: the_repository->commondir is already set to ".git". Back trace when the strbuf_getcwd() is called for the 3rd time is (frame #4 is set_git_work_tree()): * frame #0: git`strbuf_getcwd(sb=0x00007ff7bfeff0a8) at strbuf.c:588:20 frame #1: git`strbuf_realpath_1(resolved=0x00007ff7bfeff0a8, path=".", flags=2) at abspath.c:101:7 frame #2: git`strbuf_realpath(resolved=0x00007ff7bfeff0a8, path=".", die_on_error=1) at abspath.c:219:9 frame #3: git`real_pathdup(path=".", die_on_error=1) at abspath.c:240:6 frame #4: git`repo_set_worktree(repo=0x000000010044eb98, path=".") at repository.c:145:19 frame #5: git`set_git_work_tree(new_work_tree=".") at environment.c:278:2 frame #6: git`setup_discovered_git_dir(gitdir=".git", cwd=0x0000000100435238, offset=16, repo_fmt=0x00007ff7bfeff1d8, nongit_ok=0x0000000000000000) at setup.c:1119:2 frame #7: git`setup_git_directory_gently(nongit_ok=0x0000000000000000) at setup.c:1606:12 frame #8: git`setup_git_directory at setup.c:1815:9 frame #9: git`run_builtin(p=0x0000000100424d58, argc=2, argv=0x00007ff7bfeff6d8) at git.c:448:12 frame #10: git`handle_builtin(argc=2, argv=0x00007ff7bfeff6d8) at git.c:729:3 frame #11: git`run_argv(argcp=0x00007ff7bfeff54c, argv=0x00007ff7bfeff540) at git.c:793:4 frame #12: git`cmd_main(argc=2, argv=0x00007ff7bfeff6d8) at git.c:928:19 frame #13: git`main(argc=3, argv=0x00007ff7bfeff6d0) at common-main.c:62:11 At this point, precomposed_unicode is still -1 and the_repository->commondir is still NULL. This means strbuf_getcwd() retuns NFD, and the_repository->worktree is set to NFD. Moreover, precompose_string_if_needed() calls git_config_get_bool("core.precomposeunicode"), and this function indirecly sets the_repository->config->hash_initialized = 1 Later setup_git_directory_gently() (frame #7) calls setup_git_env() --> repo_set_gitdir() --> repo_set_commondir() and the_repository->commondir is now set to ".git". Then run_builtin() (frame #10) calls precompose_argv_prefix() --> precompose_string_if_needed(). Here we have precomposed_unicode = -1 the_repository->config->hash_initialized = 1 This means git_config_check_init() does not read .git/config (does not call repo_read_config()) even if the_repository->commondir is set to ".git", and precomposed_unicode is not set to 1. So the NFD in argv is not converted to NFC, and % git ls-files NFD apparently works.