99

Why does Git use

git push <remote> :<branch>

as in

git push origin :featureA

to delete the branch featureA from the remote server?

I am interested in why the colon was used as the delete flag.

It's so different from git branch -d <localbranch>.

Why don't we do something like

git branch -d --remote origin <branchname>

or is there a deeper meaning behind the colon symbol that I didn't know?

Finn Smith
  • 772
  • 2
  • 7
  • 21
scalopus
  • 2,640
  • 3
  • 19
  • 32
  • 3
    For deleting remote branches, there's now a prettier syntax [`git push origin --delete foobar`](http://git-scm.com/book/ch3-5.html#Deleting-Remote-Branches) – quetzalcoatl Nov 05 '15 at 13:56

2 Answers2

106

It is not the meaning of the : per se, but what is present, or rather absent before it.

The refspec format is

<+><source>:<destination>

(optional + for non-fast forward)

So when you do something like git push origin :featureA, you are specifying an empty source ref and basically making the destination "empty" or deleting it.

PS: Note that the refspec of : or nothing doesn't mean push nothing to nothing however. It makes git to push "matching" branches: for every branch that exists on the local side, the remote side is updated if a branch of the same name already exists on the remote side.

manojlds
  • 290,304
  • 63
  • 469
  • 417
34

The colon isn't a "delete flag". Note that git push and git pull both accept zero or more refspecs as their final argument(s). Now read about refspecs. A colon separates source from destination in a refspec. The command git push origin :foo has an empty source and essentially says "push nothing to branch foo of origin", or, in other words, "make branch foo on origin not exist".

Andris
  • 5,853
  • 3
  • 28
  • 34
Ryan Stewart
  • 126,015
  • 21
  • 180
  • 199
  • IMO, your answer doesn't answer the question for the following reason: if I try to push a branch whose history has diverged, I need to force push the branch. However, this is not the case when deleting a branch using `:foo`. An empty branch does not share history with an existing remote branch and so it cannot, the way I see it, overwrite an existing remote branch with an empty branch. Something feels wrong with your answer. – Umang Sep 05 '11 at 04:02
  • 3
    @Umang: afaik, it's only a conceptual thing, and I didn't say "push an empty branch". I said "push nothing". I don't disagree with your assessment that it would make more sense with a "+" in front of it, but this is just how it works. See the [last section](http://progit.org/book/ch9-5.html#deleting_references) of the refspecs link I posted, and decide whether you trust the author. – Ryan Stewart Sep 05 '11 at 04:06
  • I think I understand a little better now. Thanks! – Umang Sep 05 '11 at 04:27