rebase: handle --update-refs branch symrefs#2126
Conversation
9938d7e to
0ab0a71
Compare
|
/preview |
|
Preview email sent as pull.2126.git.1779908024.gitgitgadget@gmail.com |
|
/preview |
|
Preview email sent as pull.2126.git.1779943633.gitgitgadget@gmail.com |
|
/preview |
|
Preview email sent as pull.2126.git.1779943735.gitgitgadget@gmail.com |
|
/preview |
|
Preview email sent as pull.2126.git.1779944585.gitgitgadget@gmail.com |
|
/submit |
|
Submitted as pull.2126.git.1779946921.gitgitgadget@gmail.com To fetch this version into To fetch this version to local tag |
| @@ -6445,28 +6445,67 @@ static int add_decorations_to_list(const struct commit *commit, | |||
| struct todo_add_branch_context *ctx) | |||
There was a problem hiding this comment.
"Kristoffer Haugsbakk" wrote on the Git mailing list (how to reply to this email):
On Thu, May 28, 2026, at 07:42, Son Luong Ngoc via GitGitGadget wrote:
>[snip]
> -test_expect_failure '--update-refs skips branch symrefs to current branch' '
> +test_expect_success '--update-refs skips branch symrefs to current branch' '
> test_when_finished "
> test_might_fail git rebase --abort &&
> git checkout primary &&
This style of fixing a bug by:
• Add failing test `test_expect_failure` in the first commit
• Fix the bug in the next commit and flip to `test_expect_success`
Is legitimate and makes it easier to verify that the test really
exercises the regression. But in this project it is preferred to
just do the bug fix + regression test in one patch.
See https://lore.kernel.org/git/xmqqfrdk3aqy.fsf@gitster.g/
> --
> gitgitgadget|
User |
|
Junio C Hamano wrote on the Git mailing list (how to reply to this email): "Son Luong Ngoc via GitGitGadget" <gitgitgadget@gmail.com> writes:
> git rebase --update-refs can fail after the normal rebase path has
> successfully updated the current branch when another local branch is a
> symbolic ref to it.
>
> One practical way to arrive at that setup is a default branch rename from
> master to main. While the migration is in progress, a user may keep
> refs/heads/main as a symbolic ref to refs/heads/master so that both names
> continue to work locally.
>
> If pull.rebase is enabled, a plain git pull can then finish the rebase of
> master and still fail while trying to update the main alias. The reported
> failure looked like this, with line breaks adjusted for the cover letter:
>
> Successfully rebased and updated refs/heads/master.
> error: update_ref failed for ref 'refs/heads/main':
> cannot lock ref 'refs/heads/main':
> is at fc2c7bd5f17abec7861ef759edcd33a1e16662a1
> but expected 531cabdfb49098d6ffa502ed4bf91d1b35edfcfa
> Updated the following refs with --update-refs:
> Failed to update the following refs with --update-refs:
> refs/heads/main
I vaguely recall we saw a different topic that dealt with a
situation somewhat similar to this topic (I think it was about
'describe' giving a name that is not a branch). How would this mesh
with what the other topic wanted to do? Instead of filtering out
non-branch names (which the other topic did), here we want to filter
out names that are not concrete branches but pointers to something
else. Would it mean that the logic here is more broad (i.e., both
wants to filter out names of non-branches), making the other topic
unnecessary?
|
|
This patch series was integrated into seen via git@d871d43. |
0ab0a71 to
c1e8828
Compare
|
/preview |
|
Preview email sent as pull.2126.v2.git.1780062147590.gitgitgadget@gmail.com |
git rebase --update-refs can fail after the normal rebase path has updated the current branch when another local branch is a symref to it. This can happen during a default-branch rename where refs/heads/main points at refs/heads/master while users migrate. The sequencer queues update-ref commands from local branch decorations. Commit 106b688 (rebase: ignore non-branch update-refs) filters out decorations that are not local branches, such as HEAD and tags. A branch symref is different: it is still a local branch decoration under refs/heads/, but it is an alias rather than a concrete branch to update. Queuing the alias by its literal name makes the final update dereference it back to the current branch and fail the old-OID check because that branch moved earlier in the rebase. Resolve local branch symrefs to their referents before queuing update-ref commands. Skip aliases of HEAD and duplicate referents, leaving one old-OID-checked update for each concrete branch. Signed-off-by: Son Luong Ngoc <sluongng@gmail.com>
c1e8828 to
b59eb4e
Compare
|
/preview |
|
Preview email sent as pull.2126.v2.git.1780068269833.gitgitgadget@gmail.com |
|
This branch is now known as |
|
This patch series was integrated into seen via git@eb72804. |
git rebase --update-refs can fail after the normal rebase path has
updated the current branch when another local branch is a symref to it.
This can happen during a default-branch rename where refs/heads/main
points at refs/heads/master while users migrate.
The sequencer queues update-ref commands from local branch decorations.
Commit 106b688 (rebase: ignore non-branch update-refs) filters out
decorations that are not local branches, such as HEAD and tags. A branch
symref is different: it is still a local branch decoration under
refs/heads/, but it is an alias rather than a concrete branch to update.
Queuing the alias by its literal name makes the final update dereference
it back to the current branch and fail the old-OID check because that
branch moved earlier in the rebase. Resolve local branch symrefs to
their referents before queuing update-ref commands. Skip aliases of HEAD
and duplicate referents, leaving one old-OID-checked update for each
concrete branch.
Changes since v1:
non-local decorations are already filtered, and this patch handles the
remaining local branch decorations that are symref aliases.
cc: "Kristoffer Haugsbakk" kristofferhaugsbakk@fastmail.com