28

We find ourselves in the situation where master has new feature work, and feature1 (which branched off master) is the stable master. How can we change things so that they "trade places"? I.e., feature1 becomes master, and master becomes newfeaturebranch?

I found a couple similar SO questions, but in those cases they no longer cared about the old master commits. Here, we want to preserve the current master as the new newfeaturebranch.

I've thought of one way to do this:

  1. Create newfeaturebranch from the current master.
  2. Revert/delete commits from master back to feature1's branching point.
  3. Merge feature1 into master.
  4. Delete branch feature1.
Dogweather
  • 12,603
  • 15
  • 54
  • 73

3 Answers3

40

You can rename branches:

git branch -m master newfeaturebranch
git branch -m feature1 master
poke
  • 307,619
  • 61
  • 472
  • 533
  • Interesting. And then I can push these up to a remote (Github), and it'll simply work? – Dogweather Jun 19 '13 at 19:56
  • 1
    As the new master is *ahead* of the old master, Git will not complain (it will only complain if you cannot fast-forward to it). Similarly, as the `newfeaturebranch` is a completely new branch name that doesn’t exist on the remote yet, this should work as well. Only when you want to update a branch where commits are “removed”, you would have to *force push* it using `git push -f`. – poke Jun 19 '13 at 19:58
  • Thanks, this worked great. Both old branches had concurrent commits, and so a force was necessary. But that operation is to be expected: I also created "archive" branches of each of the originals, just in case anything went wrong. – Dogweather Jun 19 '13 at 21:53
  • What about others? wouldn't their local copies of the repository get confused if they were on the old master? Or would they automatically switch to `newfeaturebranch` now? – rubo77 Nov 25 '14 at 11:51
  • 1
    @rubo77 Yes, if you rename branches not only locally but on the remote too, then you should communicate with the other developers that you made this change. If they try to merge changes in, Git will refuse to do so *if* the remote contains fewer commits. In that case, a `git reset --hard origin/master` works to reset to the remote’s master by throwing everything else away (so if you have local changes, you might want to back those up in a separate branch). – poke Nov 25 '14 at 13:00
4

I started with poke's solution, but after pushing, the local branches were still tracking the old remote branches. To track the correct branches I just had to add the -u option for pushing.

git branch -m master newfeaturebranch
git branch -m feature1 master

git push -uf origin master
git push -u origin newfeaturebranch

It can be also done in two steps by first pushing and then adjusting the correct branch to track:

git push -f origin master
git push origin newfeaturebranch

git branch -u origin/master master
git branch -u origin/newfeaturebranch newfeaturebranch
0

EDIT : This post was written before you edit your question, when you were saying that you want to simply 'trade places'. If you don't need to keep names, Poke's solution is enough.


You need a third branch tmp, just like swapping variables in programming :

  • git checkout -b tmp master : switch on new tmp branch created from master
  • git branch -D master : delete branch master
  • git checkout -b master feature1 : recreate master from feature1
  • git branch -D feature1 : delete branch feature1
  • git checkout -b feature1 tmp : recreate newfeaturebranch from tmp (which is where master was at the very beginning)
Guillaume Darmont
  • 4,702
  • 1
  • 19
  • 34
  • 1
    You shouldn’t use the uppercase `-D` flag if you don’t explicitely need it. `-d` is enough. – poke Jun 19 '13 at 19:54
  • 2
    If he wants to keep the names, he could just rename `newfeaturebranch` into `feature1`, so Poke's solution is "enough" unconditionally. – Angstrom Jul 13 '17 at 17:02