Skip to content

Safer "Delete Branch & Remote" behavior #1828

Open
@dmchurch

Description

@dmchurch

Currently, when performing an unforced deletion of a branch and its remote, GitLens uses the following command sequence:

git branch --delete $branch_name
git push -d $remote_name $branch_name

This invariably succeeds (though with a warning), because the rules on unforced deletion of a local branch allow the deletion if it's up-to-date with its remote tracking branch. This makes the unforced version no safer than the forced version. A safer version uses three commands:

git branch --delete --remotes $remote_name/$branch_name
git branch --delete $branch_name
git push -d $remote_name $branch_name

The first deletes the local record of the remote tracking branch. That causes unforced-deletion to fall back to its "no-remote" behavior, which will reject the deletion if it isn't merged into HEAD - if, for example, your pull request wasn't merged yet. That way, the operation can be aborted (and, if appropriate, the user can try again with the Force option) before any potentially-irreversible changes have been made.

For an extra nice-to-have, if the unforced local deletion fails, GitLens could either (a) restore the remote-tracking branch to its previous commit, or (b) refetch the remote-tracking branch; and then restore the "upstream tracking" status of the local branch, so that the state after is the same as the state before. That makes the whole process look something like this, if it were a shell script:

remote_commit=$(git rev-list -1 refs/remotes/$remote_name/$branch_name)
git branch --delete --remotes $remote_name/$branch_name
if git branch --delete $branch_name; then
  git push -d $remote_name $branch_name
else
  git update-ref refs/remotes/$remote_name/$branch_name $remote_commit # or: git fetch $remote_name refs/heads/$branch_name:refs/remotes/$remote_name/$branch_name
  git branch --set-upstream-to=$remote_name/$branch_name $branch_name
fi

The force delete branch and remote behavior doesn't have to change at all, obviously 🙂

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions