MutantOctopus
MutantOctopus

Reputation: 3581

Git branch automatically renames on push

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.

Upvotes: 0

Views: 377

Answers (1)

torek
torek

Reputation: 488183

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.

Upvotes: 4

Related Questions