Explained: Removing remote branch in git

21 April 2009

$ git push origin :branch_to_delete_wtf_is_this_syntax?

I had used git exclusively for probably close to 5 months before I understood why the syntax for removing a remote branch was what it is. Branching, merging, forking, rebasing...I was comfortable with all that good stuff. The :branch_name syntax always bugged me, but I just accepted it in the same way I initially accepted a lot of the magic behind merge and rebase. Even though I used it relatively often, I never saw the need to "dig in", I just ran the command (after I Googled it) and went on my merry way. Then, one day it just clicked.

It seems to be a common "WTF?" for people, and I never did find a logical explanation of it. Here's my first shot at doing just that...

In order for it to make a little sense, I prefer to start in a different context though, so bear with me. Trust me though, when the dots connect you (hopefully) won't ever have to Google it again.

Here goes...

Imagine you have a local branch which you would like to push to a remote branch of a different name. To make it more tangible, let's say you want to push your local master branch to origin/master_refactor. The :branch_name syntax clicked as soon as I had to figure out how to accomplish that task...

Let's start by looking at the help for push:

$ git help push
git push [--all | --mirror | --tags] [-n | --dry-run]
         [--receive-pack=<git-receive-pack>]
         [--repo=<repository>] [-f | --force]
         [-v | --verbose] [-u | --set-upstream]
         [<repository> [<refspec>...]]

The only thing we really care about in there for this adventure is:

$ git push [<repository> <refspec>...]

So, everything in here up to the "refspec" part made perfect sense to me. When you do:

$ git push origin master

...it pushes the local "master" branch to a branch called "master" in the repository you have defined as the "origin" remote (ex: your GitHub repository). Old news.

We need to push that local branch to "origin/master_refactor"...not "origin/master". Let's look at that "refspec" garbage:

$ git help push
...
The format of a <refspec> parameter is an optional plus +, followed by the source
ref <src>, followed by a colon :, followed by the destination ref <dst>.
(...blah blah blah)
A parameter <ref> without a colon pushes the <ref> from the source repository to
the destination repository under the same name.
(...blah blah blah)

The first part is what we care about. It wasn't the easiest thing for me to understand right away, but it's basically saying that you can specify a source branch and the destination branch by separating them with a colon.

Wait! What?!

So...this is the syntax to push to a remote branch of another name:

$ git push origin master:master_refactor

Hmmm...interesting. Not the most intuitive syntax, but definitely not horrible in this context....

We're done, right?

So, now we can accomplish the task we set out to do...push to a remote branch of another name. Wait, we wanted to delete one, right? Let's just push "nothing" to that branch we just created...

$ git push origin :master_refactor

Holy. Shit.