• Duy Nguyen's avatar
    branch: fix branch renaming not updating HEADs correctly · 31824d18
    Duy Nguyen authored
    There are two bugs that sort of work together and cause
    problems. Let's start with one in replace_each_worktree_head_symref.
    
    Before fa099d23 (worktree.c: kill parse_ref() in favor of
    refs_resolve_ref_unsafe() - 2017-04-24), this code looks like this:
    
        if (strcmp(oldref, worktrees[i]->head_ref))
                continue;
        set_worktree_head_symref(...);
    
    After fa099d23, it is possible that head_ref can be NULL. However,
    the updated code takes the wrong exit. In the error case (NULL
    head_ref), we should "continue;" to the next worktree. The updated
    code makes us _skip_ "continue;" and update HEAD anyway.
    
    The NULL head_ref is triggered by the second bug in add_head_info (in
    the same commit). With the flag RESOLVE_REF_READING, resolve_ref_unsafe()
    will abort if it cannot resolve the target ref. For orphan checkouts,
    HEAD always points to an unborned branch, resolving target ref will
    always fail. Now we have NULL head_ref. Now we always update HEAD.
    
    Correct the logic in replace_ function so that we don't accidentally
    update HEAD on error. As it turns out, correcting the logic bug above
    breaks branch renaming completely, thanks to the second bug.
    
    "git branch -[Mm]" does two steps (on a normal checkout, no orphan!):
    
     - rename the branch on disk (e.g. refs/heads/abc to refs/heads/def)
     - update HEAD if it points to the branch being renamed.
    
    At the second step, since the branch pointed to by HEAD (e.g. "abc") no
    longer exists on disk, we run into a temporary orphan checkout situation
    that has been just corrected to _not_ update HEAD. But we need to update
    HEAD since it's not actually an orphan checkout. We need to update HEAD
    to move out of that orphan state.
    
    Correct add_head_info(), remove RESOLVE_REF_READING flag. With the flag
    gone, we should always return good "head_ref" in orphan checkouts (either
    temporary or permanent). With good head_ref, things start to work again.
    Noticed-by: 's avatarNish Aravamudan <nish.aravamudan@canonical.com>
    Signed-off-by: Duy Nguyen's avatarNguyễn Thái Ngọc Duy <pclouds@gmail.com>
    Signed-off-by: 's avatarJunio C Hamano <gitster@pobox.com>
    31824d18
worktree.c 8.66 KB