Steven Steven - 2 months ago 8
Git Question

Renaming a remote branch that doesn't exist locally

I'm relatively new to git. I'm using bitbucket as my remote repository. After an attempt at converting all my branches to tags, I'm in a bit of a messy situation. I'm at a state where on bitbucket I have tags that have the same name as branches. I want to remove the extraneous remote branches.

Locally, I have what I want:

> git branch
* master

> git tag
1.1.0
1.2.0
1.3.0
1.3.1
1.3.2
2.0.1


So far so good.

On bitbucket, however, I have:

branches:

1.1.0
1.2.0
1.3.0
1.3.1
1.3.2
2.0.1
master


tags:

1.1.0
1.2.0
1.3.0
1.3.1
1.3.2
2.0.1


I want to delete all remote branches except master. How do I do this?

Thanks.

Answer

To delete a remote object you have to push nothing to it — for instance,

git push origin :master

will delete whatever is named "master" in the remote repository.

Now the truth is that "master" here is just a shortcut for the full real name of that reference which is "refs/heads/master". Tags are in the "refs/tags" namespace, so if you happen to have both a branch and a tag named "foo" in your remote repository, you can use the full name of an object you want to delete to remove any ambiguity.

The gory details are described in the gitrevisions(7) manual page.

So, to delete all the remote branches except master you have to do something like this:

git push origin :refs/heads/1.1.0 :refs/heads/1.2.0 ...

You could try to make this less tedium by employing a little shell hack:

$ ( while read b; do echo :refs/heads/$b; done | xargs git push origin )
1.1.0
1.2.0
1.3.0
1.3.1
1.3.2
2.0.1
^D

(^D here means pressing ctrl-d to signalize end of input to the subshell).


P.S. By the way, I thought that since Git supports wildcard refspecs when fetching, like

git fetch origin '+refs/heads/*:refs/heads/*'

that would work for pushing, too. But seems like it doesn't — at least

git push origin ':refs/tags/*'

does not seem to work for me with Git 1.8.1.

Comments