4

On the command-line, I often do this

git branch -D -r origin/feature/someLabelHere

to remove a remote branch after a pull request from that branch has been merged into master. I know now to do

git branch -d feature/someLabelHere

in magit, but not the -D -r equivalent. How can one?

Simply pressing k to ask for removal on the displayed remote branch gets an error message and reference to the process buffer where one sees e.g.

  1 git … push origin :bugfix/someLabelHere        
error: unable to delete 'bugfix/someLabelHere': remote ref does not exist  
error: failed to push some refs to 'git@github.com:eddelbuettel/somerepo.git'    

Edit: It may have been an 'order of commands' issue. Deleting in magit before removing the remote branch at github seems to do the trick.

  • I don't understand the question, deleting remote and local branches works the same way in magit. – npostavs Sep 16 '16 at 15:49
  • For the local one, it works as expected as you say. But if I hit 'k' on the remote branch, I get an error message with a reference to the magit buffer. So the pressing 'k' does not translate to command I want to be executed. Hence my question here. – Dirk Eddelbuettel Sep 16 '16 at 15:51
  • Please add this info (and the exact error message) to the question. – npostavs Sep 16 '16 at 15:52
  • 1
    "[git branch -D -r] very much is sufficient [to delete remote branches]" - not according to the manual: "it only makes sense to delete remote-tracking branches if they no longer exist in the remote repository" – npostavs Sep 16 '16 at 22:00
  • 1
    Quite possibly. The operation that failed on me was tried a dozen+ times -- but seemingly I always removed the remote side first. I then tried to remove the local index of that remote, and that failed on me. Quite possibly my bad as may not have pulled all remote references. My main beef was this: I have a working flow on the command-line (where the remote-removed seemingly does not matter) and I failed to get all of it to magit. I am not saying magit has a bug -- I am merely stating what we all know: git is complex, and documentation is hard. – Dirk Eddelbuettel Sep 18 '16 at 2:32
8

Edit: The below description is of course still accurate, but it should be noted that Magit now falls back to deleting just the local remote-tracking ref if the respective branch does not actually exist on the remote anymore.


Pulling out the relevant information from the question comments:

Magit does not provide a direct equivalent of git branch -D -r <remote>/<branch>. The --prune flag from the fetch popup (by default, f-p) can be used instead to delete all stale remote-tracking for a particular remote.

I believe that Magit doesn't provide a command for git branch -D -r because it is the assumed that it would be rare for a user to want to delete a single stale remote-tracking branch but not prune other stale remote-tracking branches for that remote.


If the branch does still exist on a remote, k will run git push <remote> :<branch>, deleting the branch on the remote and cleaning up the local remote-tracking branch. So, provided that the branch hasn't been deleted from the remote in some other way (e.g., through GitHub's web interface or by running git push <remote> :<branch> from another machine), this command is all you need to run (at least until you get on another machine and want to prune the remote-tracking branches there).

Unlike git push <remote> :<branch>, git branch -D -r <remote>/<branch> is not sufficient to delete the branch on the remote. This is described in man git-branch:

Use -r together with -d to delete remote-tracking branches. Note, that it only makes
sense to delete remote-tracking branches if they no longer exist in the remote
repository or if git fetch was configured not to fetch them again. See also the prune
subcommand of git-remote(1) for a way to clean up all obsolete
remote-tracking branches.

The example below shows what the above quote is talking about. If you just use git branch -D -r, the local remote-tracking branch will deleted just to be recreated on the next fetch.

set -x

# Repo setup

mkdir remote-repo
cd remote-repo
git init --bare

cd ..
mkdir local-repo
cd local-repo

git init
echo text > some-file
git add some-file
git commit -m"Add some file"
git checkout -b feat master
echo text > feat-file
git add feat-file
git commit -m"Add feature file"
git remote add origin ../remote-repo
git push origin feat master

# branch -D -r test

git branch -D -r origin/feat
ls .git/refs/remotes/origin/

git fetch origin
ls .git/refs/remotes/origin/

But a git push origin :feat (or, in Magit, k and then selecting origin/feat) will get rid of the branch in both places.

git push origin :feat
ls .git/refs/remotes/origin/

git fetch origin
ls .git/refs/remotes/origin/
  • "...because it is the assumed that it would be rare...". Yes, but we might still want to (if (member branch ls-remote) (push :branch) (branch-D branch)). – tarsius Sep 18 '16 at 13:37
  • @tarsius yes, worth considering. I suppose the main downside of that is needing to reach out to the remote a second time. (And I suppose getting the error from git is a good indication that the remote may need pruning in general.) – Kyle Meyer Sep 18 '16 at 13:59
  • Try-catch might be better, but is also more work. – tarsius Sep 18 '16 at 14:42
  • I've opened an issue for this: github.com/magit/magit/issues/2778. – tarsius Sep 18 '16 at 14:45
  • 1
    In favour -- one other case where this bites me sometimes is two machines working on the same branch, call'em desktop and laptop. If I do the procedure (in the all-important right order I now learned about) on the desktop I still have a pending branch on the laptop I can only nuke from the command-line. Not ideal, so in favour of extending magit for that. – Dirk Eddelbuettel Sep 18 '16 at 15:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.