From: Abhinav Gupta <mail@abhinavg.net>
The following Git configuration breaks git rebase --update-refs:
[rebase]
instructionFormat = %s%dThe '%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 HEADTo fix, ignore decorations that are not local branches when scanning through the table.
This filtering matches the documented contract:
Automatically force-update any branches that point to commits [..]
Signed-off-by: Abhinav Gupta <mail@abhinavg.net> --- sequencer.c | 10 ++++++++++ t/t3404-rebase-interactive.sh | 22 ++++++++++++++++++++++ 2 files changed, 32 insertions(+)
Show changes to 2 files +32 −0
sequencer.c, t/t3404-rebase-interactive.sh
diff --git a/sequencer.c b/sequencer.c index b7d8dca47f..25bcfc5da0 100644 --- a/sequencer.c +++ b/sequencer.c @@ -6428,6 +6428,16 @@ static int add_decorations_to_list(const struct commit *commit, const char *path; size_t base_offset = ctx->buf->len; + /* + * The global decoration table may contain names loaded by + * a previous pretty format such as "%d". + * This will result in refs such as "HEAD" being present. + */ + if (decoration->type != DECORATION_REF_LOCAL) { + decoration = decoration->next; + continue; + } + /* * If the branch is the current HEAD, then it will be * updated by the default rebase behavior. diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index 3e44562afa..d58236f0eb 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -1960,6 +1960,28 @@ test_expect_success '--update-refs adds commands with --rebase-merges' ' ) ' +test_expect_success '--update-refs ignores non-branch decorations' ' + test_when_finished "git branch -D update-refs" && + test_when_finished "git branch -D third" && + test_when_finished "git checkout primary" && + git checkout -B update-refs no-conflict-branch && + git branch -f third HEAD~1 && + ( + set_cat_todo_editor && + + # rebase.instructionFormat=%d loads normal log decorations before + # --update-refs adds its branch placeholders. + # The placeholder scan must still ignore symbolic decorations, + # because "update-ref HEAD" is not a valid branch update. + test_must_fail git -c rebase.instructionFormat="%s%d" \ + rebase -i --update-refs primary >todo && + + test_grep "^update-ref refs/heads/third$" todo && + test_grep ! "^update-ref refs/heads/update-refs$" todo && + test_grep ! "^update-ref HEAD$" todo + ) +' + test_expect_success '--update-refs updates refs correctly' ' git checkout -B update-refs no-conflict-branch && git branch -f base HEAD~4 && base-commit: 94f057755b7941b321fd11fec1b2e3ca5313a4e0
-- 2.54.0