0

I have a weird problem. I'm using Github, and attempting to rename a branch. I've already read about renaming branches in other questions, and I'm following the instructions to the letter, encountering a number of errors.

First, the situation: I have a branch named Framework, which I now realize should be better titled "Platform-Control-Dev" as its contents shifted from interfaces to implementations. The first thing I did, after renaming locally, was the simplest command I've seen: git push origin :Framework Platform-Control-Dev. That resulted in an error about "dst ref refs/heads/Framework receives from more than one src". I then decided to go step by step; git push origin :Framework successfully deleted the remote branch. However, when I made an attempt to push the renamed, local branch back, it renamed itself to Framework.

* [new branch]      Platform-Control-Dev -> Framework

None of the answers I've seen about this problem address this issue, and I'm at my wits' end trying to figure out why it's doing this. If anyone knows why, and how to fix it, it would be appreciated.

Community
  • 1
  • 1
MutantOctopus
  • 3,431
  • 4
  • 22
  • 31
  • The easiest way to accomplish what you're trying to do is just create a new branch and delete the old one. The commits and everything will be the exact same. The only downside I can think of is that if you're working with other people, they'll have to do the same. – EmptyArsenal Nov 09 '15 at 17:26
  • I'd rather not do that -- I'd much rather figure out why this is failing to work for me when it seems to work for others. – MutantOctopus Nov 09 '15 at 17:30

1 Answers1

4

Forgive the restatement of the obvious here, but: you're running git push origin refspec.

The key to your problem is how push handles a refspec that lacks a colon :, i.e., is just a source-specifier.

Normally when pushing a branch, you push to the same branch-name upstream, unless you've already set a named upstream. In that case, your git discovers that the upstream is remapped: your local branch Platform-Control-Dev corresponds to origin's Framework. So your git re-maps in the upwards direction, just as it does in the downwards (fetch-and-then-(merge|rebase)) direction.

You can delete the upstream setting (wiping out the mapping), or simply push to a two-part refspec:

git push origin Platform-Control-Dev:Platform-Control-Dev

(Incidentally, I have gotten into the habit of using git push <remote> HEAD:<branch> since I'm often working in a local branch that's tracking my own "main" local branch, instead of something copied directly from the remote in question. This has its own hazards, though: I have to be careful to name the correct <branch> every time. :-) )

(Also, by the way, this is why you got the two-sources (receives from more than one src) error: your git decided to set the upstream Framework ref to both nothing—delete it—and the SHA-1 from your Platform-Control-Dev.)


Edit: As you discovered, as long as the old upstream setting is in place, your git will keep re-creating the Framework branch name on the server. (Also your git will not pick up changes from the new upstream automatically, which may even be worse.)

To see the upstream setting, view your .git/config file, and you'll see (along with all the other stuff in there):

[branch "Platform-Control-Dev"]
    remote = origin
    merge = refs/heads/Framework

The origin part is correct but the merge part refers to the old branch name on the server, and that's where the old branch name keeps coming from.

You can fix this manually (which is what I tend to do because the "nice" options below were not in git when I first started doing this stuff), or with one of the following. Note that --set-upstream-to and --unset-upstream work on the current branch (by default) so you should have your Platform-Control-Dev branch checked out.

  • The new, easy way:

    $ git branch --set-upstream-to origin/Platform-Control-Dev
    

    (this is the one to use as long as your git is not too ancient to have --set-upstream-to).

  • The old-school method:

    $ git config branch.Platform-Control-Dev.merge refs/heads/Platform-Control-Dev
    

    (or edit .git/config, which is what I usually still do!)

  • The "remove the upstream setting entirely" method:

    $ git branch --unset-upstream
    

    After this, you can use a regular git push -u to set it. Since no upstream is set at this time, push won't (can't) re-map back to the old name. Instead, it will create or update the new name, and then do a git branch --set-upstream-to for you, using the new name.

torek
  • 448,244
  • 59
  • 642
  • 775
  • I won't pretend to understand most of Git's intricacies, but I'm glad that there are people who do. Thanks! But when you said "delete the upstream setting", what did *that* mean? – MutantOctopus Nov 09 '15 at 17:39
  • And then when I try to publish again, it recreates the Framework branch. Does this have to do with the fact that the mapping is still missing? How do I set platform-control-dev local to be the same as the remote? – MutantOctopus Nov 09 '15 at 17:41
  • The upstream setting for any given branch is (for historical reasons) stored in two parts in the configuuration (`git config -e` or `cat .git/config` to see it). To remove it, you can run two `git config` steps, or use the new `git branch --unset-upstream` command. Or, you set the upstream to the new name, again either with two `git config` commands or the new `git branch --set-upstream-to ` command. These could use some formatting, I'll edit them in. – torek Nov 09 '15 at 17:43
  • Perfect! Thanks! it still seems odd that others seemed to have such an easy time, though. Heh. – MutantOctopus Nov 09 '15 at 17:46