git rebase writes worktree "Ref ... checked out at ..." todo comments with a hardcoded '#', breaking parsing when core.commentChar is not '#'.
"Markus Geiger" <[email protected]> Mon, 3 Aug 2026 09:46:39 +0200 (CEST)
| Newsgroups | org.kernel.vger.git |
|---|---|
| Message-ID | <[email protected]> |
When core.commentChar is set to a non-'#' value (e.g. ';') AND a branch that falls within the rebased commit range is checked out in another worktree, `git rebase` generates a todo list in which the informational "Ref ... checked out at ..." lines are prefixed with a hardcoded '#' instead of the configured comment character. Git's own sequencer then re-reads that todo, does not recognize '#' as a comment, and aborts with `error: invalid command '#'`. Minimal, self-contained reproduction: T=$(mktemp -d); export HOME="$T" git config --global user.email [email protected] git config --global user.name t git config --global init.defaultBranch main cd "$T"; git init -q super && cd super echo a > f && git add f && git commit -qm base # upstream (ancestor) echo b >> f && git commit -qam A echo c >> f && git commit -qam B git branch feat git checkout -q feat # primary worktree on 'feat' git worktree add -q ../mainwt main # 'main' (in range) checked out elsewhere git config core.commentChar ';' # <-- the trigger git rebase main~2 # replay A, B onto 'base' What did you expect to happen? (Expected behavior) Rebase succeeds, exactly as it does with the default core.commentChar='#'. The "Ref ... checked out at ..." advisory lines are informational comments and should be ignored by the sequencer. What happened instead? (Actual behavior) error: invalid command '#' error: invalid line 3: # Ref refs/heads/main checked out at '.../mainwt' error: invalid command '#' error: invalid line 5: # Ref refs/heads/feat checked out at '.../super' You can fix this with 'git rebase --edit-todo' and then run 'git rebase --continue'. Exit code 1, with a half-initialized rebase left in progress. What's different between what you expected and what actually happened? The generated rebase-merge/git-rebase-todo mixes two comment characters, which shows one code path respects core.commentChar while another hardcodes '#': pick 2fbb49f A pick 15691cb B # Ref refs/heads/main checked out at '.../mainwt' <-- hardcoded '#' (BUG) # Ref refs/heads/feat checked out at '.../super' <-- hardcoded '#' (BUG) ; Rebase a0b3bf8..15691cb onto a0b3bf8 (2 commands) <-- correct ';' (respects config) On re-read, todo_list_parse_insn_buffer() treats any line not starting with the configured comment char as an instruction, so '#' is parsed as a command. Anything else you want to add: Root cause: the sequencer code (sequencer.c) that appends the "Ref <ref> checked out at <path>" advisory lines when a ref in the rebased range is checked out in another worktree prepends a literal '#' rather than the resolved comment_line_char. Suggested fix: use comment_line_char for those lines, as the surrounding template lines already do. Trigger conditions (both required): 1. core.commentChar set to a value other than '#' (also affects 'auto' when it resolves to a non-'#' character). 2. A branch within the rebased range is checked out in another worktree. Impact: `git rebase` is unusable from the CLI for users who set a custom core.commentChar (common for teams that begin commit-message lines with '#123' issue refs) as soon as they use worktrees. Workarounds: - git -c core.commentChar='#' rebase ... - set core.commentChar='#' globally - git rebase --edit-todo and delete the offending '#' lines by hand Reproduced on git version 2.43.0 (details below). Not yet checked against master. Please review the rest of the bug report below. You can delete any lines you don't wish to share. [System Info] git version: git version 2.43.0 cpu: x86_64 no commit associated with this build sizeof-long: 8 sizeof-size_t: 8 shell-path: /bin/sh uname: Linux 7.0.0-28-generic #28~24.04.1-Ubuntu SMP PREEMPT_DYNAMIC Wed Jul 1 15:50:57 UTC 2 x86_64 compiler info: gnuc: 13.3 libc info: glibc: 2.39 $SHELL (typically, interactive shell): /usr/bin/zsh [Enabled Hooks]