rebase: ignore non-branch update-refs

The following Git configuration breaks git rebase --update-refs: [rebase] instructionFormat = %s%d The '%d' format requests all available decorations for a commit, filling the global decoration table with all of them, which --update-refs then uses to populate 'update-ref' instructions in the rebase todo list. Specifically, this results in the following instruction: update-ref HEAD The todo parser then rejects the instruction: error: update-ref requires a fully qualified refname e.g. refs/heads/HEAD error: invalid line 3: update-ref HEAD To fix, ignore decorations that are not local branches when scanning through the table. This matches the documented contract: it moves branch refs under refs/heads/ and leaves display-only decorations (HEAD, tags, etc.) alone. Verification: A regression test that fails without this fix is included. Signed-off-by: Abhinav Gupta <mail@abhinavg.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Abhinav Gupta committed May 10, 2026 at 15:41 UTC 106b6885c7bbaafc863dff0bb5361f906545de5c
2 files changed +25 -1
sequencer.c
+7 -1
@@ -6361,8 +6361,14 @@ static int add_decorations_to_list(const struct commit *commit,
6361 /*
6362 * If the branch is the current HEAD, then it will be
6363 * updated by the default rebase behavior.
6364 + * Exclude it from the list of refs to update,
6365 + * as well as any non-branch decorations.
6366 + * Non-branch decorations may be present if the pretty format
6367 + * includes "%d", which would have loaded all refs
6368 + * into the global decoration table.
6369 */
6365 - if (head_ref && !strcmp(head_ref, decoration->name)) {
6370 + if ((head_ref && !strcmp(head_ref, decoration->name)) ||
6371 + (decoration->type != DECORATION_REF_LOCAL)) {
6372 decoration = decoration->next;
6373 continue;
6374 }
t/t3404-rebase-interactive.sh
+18
@@ -1954,6 +1954,24 @@ test_expect_success '--update-refs adds commands with --rebase-merges' '
1954 )
1955 '
1956
1957 +test_expect_success '--update-refs ignores non-branch decorations' '
1958 + test_when_finished "git branch -D update-refs" &&
1959 + test_when_finished "git checkout primary" &&
1960 + git checkout -B update-refs no-conflict-branch &&
1961 + (
1962 + set_cat_todo_editor &&
1963 +
1964 + # rebase.instructionFormat=%d loads normal log decorations before
1965 + # --update-refs adds its branch placeholders so we must ignore
1966 + # all non-local decorations.
1967 + test_must_fail git -c rebase.instructionFormat="%s%d" \
1968 + rebase -i --update-refs HEAD^ >todo
1969 + ) &&
1970 + grep ^update-ref todo >actual &&
1971 + test_write_lines "update-ref refs/heads/no-conflict-branch" >expect &&
1972 + test_cmp expect actual
1973 +'
1974 +
1975 test_expect_success '--update-refs updates refs correctly' '
1976 git checkout -B update-refs no-conflict-branch &&
1977 git branch -f base HEAD~4 &&