2095

I have two branches in my Git repository:

  1. master
  2. seotweaks (created originally from master)

I created seotweaks with the intention of quickly merging it back into master. However, that was three months ago and the code in this branch is 13 versions ahead of master.

It has effectively become our working master branch as all the code in master is more or less obsolete now.

Very bad practice I know, lesson learned.

Do you know how I can replace all of the contents of the master branch with those in seotweaks?

I could just delete everything in master and merge, but this does not feel like best practice.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jason
  • 22,645
  • 5
  • 29
  • 51
  • 3
    Also, this question is better worded and is missing the confusion caused by the "Extra" comment added to the question after answers had started. – Rob Osborne May 10 '16 at 11:20
  • There is a simple way using checkout, if and only if you are not worried about commit histories of seotweaks. Switch to master branch first, then run, `git checkout seotweaks -- *` then run, `git commit -m "Replaced contents of master with seotweaks"` finally run `git push` – learner Sep 17 '19 at 17:06

5 Answers5

3526

You should be able to use the “ours” merge strategy to overwrite master with seotweaks like this:

git checkout master
git pull
git checkout seotweaks
git merge -s ours master
git checkout master
git merge seotweaks

The first two steps are a useful precaution to ensure your local copy of master is up-to-date. The result should be that your master is now essentially seotweaks.

(-s ours is short for --strategy=ours)

From the docs about the 'ours' strategy:

This resolves any number of heads, but the resulting tree of the merge is always that of the current branch head, effectively ignoring all changes from all other branches. It is meant to be used to supersede old development history of side branches. Note that this is different from the -Xours option to the recursive merge strategy.

Update from comments: If you get fatal: refusing to merge unrelated histories, then change the second line to this: git merge --allow-unrelated-histories -s ours master

Roly
  • 2,126
  • 2
  • 20
  • 34
ergosys
  • 47,835
  • 5
  • 49
  • 70
  • 39
    @Joel Berger, the recursive merge options will mix the two branches, favoring "theirs" or "ours" only on conflict. So you'll get changes from both branches. – ergosys Oct 21 '11 at 18:23
  • 47
    This isn't working for me. When I do "git merge -s ours master" from the other branch, I get "Already up-to-date." Anything else I can try? – elsurudo Mar 09 '12 at 16:58
  • 4
    @elsurudo It's probably not an error: http://stackoverflow.com/a/634575/240633 – ergosys May 04 '12 at 19:40
  • 2
    Since I am working on remote branches, I need to push after every merge? – Eric Jan 24 '14 at 17:29
  • I ran into the exact same problem the original posted did and this approach replaced master with my desired branch within 2 minutes. Thank you. – Dave Collier Mar 27 '14 at 15:12
  • 4
    the rename strategy posted by @ZelluX below better solves this problem. This answer will just merge a cleaned up branch on top of your existing master – Milimetric May 13 '14 at 12:45
  • 2
    @ergosys Is there any advantage to this approach than ZelluX's method of renaming the branches? This one looks rather misleading later on when you look at the merge, but perhaps the renaming approach has a disadvantage? – golddove Jun 17 '14 at 05:57
  • 4
    Other than VonC's answer, which raises some issues, you don't retain any non-conflicting changes from the old master when you rename. You may not mind this, depends on the situation. – ergosys Jun 17 '14 at 07:59
  • I like this solution because it keeps changes locally to be verified before overriding master!!! – KateYoak May 23 '15 at 00:22
  • Why are steps 3 and 4 needed when you already replaced the master branch ins step 1 and 2 – jantristanmilan Oct 24 '15 at 09:05
  • 1
    Worked for me. Remember to push *both* branches if you're trying to fix a remote repo like github or bitbucket. – JamesQMurphy Dec 15 '15 at 22:06
  • 2
    This preserved all the commits on master :( Did I do it wrong? – Stop Slandering Monica Cellio Dec 21 '15 at 17:19
  • 1
    Did those steps - looked like did something locally, but it didn't. Luckily, I made a copy of my working dir first on the newer-branch - did a compare between that and the 'master' branch I supposedly updated. Nothing had been updated (typical git). Erased the files on the master-branch's dir (except .git), replaced it with the work in the dir with the newer-branch work, then git add-ed and committed - done. Lesson: make full-backups before 'git' anything. – JosephK Jan 07 '16 at 08:14
  • 2
    this does not work. I have to now resolve conflicts. Does not replace master. No different then merging 2 branches. – ssal Jan 26 '16 at 23:41
  • 2
    this would merge master into your branch ?? which is not what you want - you want to entirely replace master with another branch - or did I misunderstand ? – serup May 03 '16 at 10:39
  • I did this and did git push after. Effectively the master commits disappeared and was subsituted by the branches commits. IS there a way to reverse these commands? – Renato Mar 22 '17 at 10:05
  • @Renato you can see if you can revert to a previous state using reflog. See http://gitready.com/intermediate/2009/02/09/reflog-your-safety-net.html – ergosys Mar 22 '17 at 15:47
  • @elsurudo after renaming, simplest solution - push your local develop branch "master" to a remote branch "master" ```git push origin master:master``` http://stackoverflow.com/questions/2936652/git-push-wont-do-anything-everything-up-to-date – Michael Dimmitt May 09 '17 at 07:22
  • This approach worked great for me. We had a beta branch that was being treated as master, and a master branch that hadn't been touched in over a year. The only thing i did a little different was a git push before i merged beta into master. "git checkout beta" -> "git merge -s ours master" -> "git push" -> "git checkout master" -> "git merge beta" -> "git push" – Donuts May 10 '17 at 16:32
  • Most simply, assuming you do not care about losing master you could run `git push -f origin seotweaks:master` – PiersyP Feb 15 '18 at 11:24
  • To avoid the need for a commit message: `git merge -s ours --no-commit master` – Matt Jun 06 '18 at 13:49
  • 4
    When I do the second step I get `fatal: refusing to merge unrelated histories`. What do I do now? – Udayaditya Barua Aug 08 '18 at 08:10
  • But why is the merge commit message `Merge branch 'master' into other` instead of `Merge branch 'other' into master`? And why is this commit on both of the branches? It doesn't make sense for the merge to be on the `other` branch, as this branch should be the one that gets merged in `master`. – Iulian Onofrei Aug 20 '18 at 08:38
  • From what I understand, this actually merged the `master` branch into the `other` branch, and then fast-forwards the `master` branch. – Iulian Onofrei Aug 20 '18 at 08:47
  • 17
    If you get `fatal: refusing to merge unrelated histories`, then change the second line to this: `git merge --allow-unrelated-histories -s ours master` – code4kix Aug 21 '18 at 13:45
  • Does this approach preserve the history of the original master? – ntaj Sep 24 '19 at 19:53
  • 2
    It is still merging 2 branches histories... I want to replace `master` entirely with `seotweaks`... – BartusZak Feb 18 '20 at 07:30
  • This can not be the answer, that is the answer https://stackoverflow.com/a/2862606/415078 – angularrocks.com Feb 21 '20 at 02:56
  • 1
    Not a good answer. This will still merge changes from master into your new branch and have unpredictable results. It's best to do the rename as stated below. – NickJ Apr 14 '20 at 02:47
  • Still don't get how this thing works, lol. After first merge the `seotweaks` actually stays the same and master is the same. So after second merge master should contain both changes, isn't it? Does that last merge commit negate the master changes? – Sergiy Ostrovsky May 08 '20 at 14:28
  • Type `:q` then press `enter` to save the commit file after `git merge -s ours master`. – Reed Jul 15 '20 at 15:28
  • https://git-scm.com/docs/git-merge#Documentation/git-merge.txt-ours . It will not work always, to quote the source ```Changes from the other tree that do not conflict with our side are reflected in the merge result.``` It did not work for me, as I had cleanly merging commits in my branch which was being overwritten. – NiharGht Aug 12 '20 at 16:37
  • @NiharGht Your quote is from the recursive ours which is different. Look a bit further down for the documentation about only ours option. – Pooks Sep 11 '20 at 07:59
  • Worked really well for me. Just had to remember that my 'master' branch was named 'main'. – Alain Dec 09 '21 at 07:36
  • Don't forget to ```git push``` at the end – Ronan Ca Nov 02 '22 at 09:34
  • The only answer on all the internet that WORKS !!! I lost 2 hours finding a way to achieve this EFFECTIVELY. THANKS – naspy971 Jun 26 '23 at 08:48
625

What about using git branch -m to rename the master branch to another one, then rename seotweaks branch to master? Something like this:

git branch -m master old-master
git branch -m seotweaks master
git push -f origin master

This might remove commits in origin master, please check your origin master before running git push -f origin master.

ZelluX
  • 69,107
  • 19
  • 71
  • 104
  • 1
    Sorry, when I run this, the changes happen only locally. How can I get this to effect the remote branches? Thanks – Jason May 19 '10 at 03:47
  • 38
    @Jason: Try `git push -f origin master` – Koraktor May 19 '10 at 08:08
  • 11
    This is probably the best way to do a forced update after ensuring your master can be completely replaced – Hrishi Feb 16 '14 at 16:20
  • you can just do it in two steps: git branch -m oldbranch newbranch; git checkout mynewmaster; git checkout -b master; .... well, two anyway :-) – Alejandro Moreno May 06 '14 at 14:26
  • 18
    It might be worth explaining that this answer possibly removes commits that were in the original `master` branch. While ergosys' solution does a proper merge and so retains all history in `master`. – florisla Aug 28 '15 at 08:05
  • 57
    Crap I just lost all commits in the original master. – moberme Nov 19 '15 at 17:50
  • I also found this: http://stackoverflow.com/a/13307342/339803 using `theirs` – redfox05 Apr 28 '16 at 05:30
  • 5
    @moberme you can do `git checkout old-master && git push origin old-master` to create a branch with the old master. – Sander Visser May 11 '16 at 10:06
  • 3
    Finalize with `git push origin :seotweaks` to remove the old ref from origin – rfabbri Dec 01 '16 at 23:16
  • If you use this method and want to keep both branches (for example if you wanted to force push code from `staging` to replace `master`, but want to keep both branches after), just rename both branches to their original names after force push, and right after that do `git checkout master` and run `git fetch --all` and `git reset --hard origin/master`. This will force your local `master` history to align with remote's. – nickang Sep 29 '17 at 03:40
  • This worked on gitlab. You have to run following before you do this. `git checkout seotweaks` – Sacky San May 17 '18 at 12:32
  • 1
    This doesn't actually work...Just really messed up my repo – Eric Aug 23 '18 at 16:49
  • downvote for just renaming branches not merging – blurfx Nov 29 '18 at 14:40
  • 3
    This is what I was looking for, to actually replace master in its entirety instead of merging (and the title does ask "How to replace master branch"). But instead of the final `git push -f origin master` I did instead `git branch -u origin/master` to set the upstream. In my case the changes to remove were not in the remote. – Daniel Jun 25 '19 at 17:17
  • @Daniel brings up a good point, to really do this you need to add `git branch -u origin/master` to the mix if the original branch is already tracked by a remote. – Kevinleary.net Nov 19 '19 at 18:56
88

You can rename/remove master on remote, but this will be an issue if lots of people have based their work on the remote master branch and have pulled that branch in their local repo.
That might not be the case here since everyone seems to be working on branch 'seotweaks'.

In that case you can:
git remote --show may not work. (Make a git remote show to check how your remote is declared within your local repo. I will assume 'origin')
(Regarding GitHub, house9 comments: "I had to do one additional step, click the 'Admin' button on GitHub and set the 'Default Branch' to something other than 'master', then put it back afterwards")

git branch -m master master-old  # rename master on local
git push origin :master          # delete master on remote
git push origin master-old       # create master-old on remote
git checkout -b master seotweaks # create a new local master on top of seotweaks
git push origin master           # create master on remote

But again:

  • if other users try to pull while master is deleted on remote, their pulls will fail ("no such ref on remote")
  • when master is recreated on remote, a pull will attempt to merge that new master on their local (now old) master: lots of conflicts. They actually need to reset --hard their local master to the remote/master branch they will fetch, and forget about their current master.

Update/Note 2022:

    git branch -m main main-old  # rename main on local
    git push origin :main          # delete main on remote
    git push origin main-old       # create main-old on remote
    git switch -c main seotweaks # create a new local main on top of seotweaks
    git push origin main           # create main on remote
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • Thanks for the detailed response, when I run 'git push remote :master' I get an error - 'remote' does not appear to be a git repository. – Jason May 19 '10 at 04:02
  • @Jason: I changed that to 'origin' which might be the default name given to your remote repo. – VonC May 19 '10 at 04:08
  • 1
    @VonC: I'm trying to do that on git-hub repository, but when trying to perform 'git push origin :master' I get a message '[remote rejected] master (deletion of the current branch prohibited)'. As for why I'm doing that... basically I severely mixed up things, importing two times the same patches through github interface and command line push, then getting everything back to work by manual merge. After that I also created another branch with a clean history, but too late... anyway. As it's on my personal experimental repository I should be the only one impacted. – kriss Aug 24 '11 at 08:00
  • 5
    @kriss: GitHub will refuse by default any push rewriting/removing history, unless you force the push: `git push -f origin :master`. – VonC Aug 24 '11 at 08:08
  • 4
    thanks this was a big help; I had to do one additional step, click the 'Admin' button on github and set the 'Default Branch' to something other than 'master', then put it back afterwards – house9 Oct 12 '11 at 19:07
  • @house9: good point. I have edited my answer to include that step. – VonC Oct 12 '11 at 19:21
50

Since seotweaks was originally created as a branch from master, merging it back in is a good idea. However if you are in a situation where one of your branches is not really a branch from master or your history is so different that you just want to obliterate the master branch in favor of the new branch that you've been doing the work on you can do this:

git push [-f] origin seotweaks:master

This is especially helpful if you are getting this error:

! [remote rejected] master (deletion of the current branch prohibited)

And you are not using GitHub and don't have access to the "Administration" tab to change the default branch for your remote repository. Furthermore, this won't cause down time or race conditions as you may encounter by deleting master:

git push origin :master
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
mholm815
  • 2,009
  • 19
  • 14
  • Does not work on Heroku: ! [rejected] -> master (non-fast-forward) error: failed to push some refs to '.git' – shaioz Mar 03 '14 at 15:42
  • 3
    git push -f origin seotweaks:master worked for me – Tom Andersen Jan 14 '16 at 17:51
  • 1
    This was by far the easiest way for me to get extensive changes on a working branch, with many difficult conflicts (due to folders being deleted and renamed), back onto master. I don't know if this is appropriate for every case (probably not), but it totally worked for me just getting everything off a branch I was done with back onto master (the working branch remains after the operation, but both branches appear to now have the same commits). – Ben Stahl Jun 13 '19 at 01:06
  • How does the `master` git history looks like after `force push`? Does it overwrite all files on `master` even when they weren't changed on `seotweaks`? – BartusZak Feb 18 '20 at 11:55
8

I found this to be the best way of doing this (I had an issue with my server not letting me delete).

On the server that hosts the origin repository, type the following from a directory inside the repository:

git config receive.denyDeleteCurrent ignore

On your workstation:

git branch -m master vabandoned                 # Rename master on local
git branch -m newBranch master                  # Locally rename branch newBranch to master
git push origin :master                         # Delete the remote's master
git push origin master:refs/heads/master        # Push the new master to the remote
git push origin abandoned:refs/heads/abandoned  # Push the old master to the remote

Back on the server that hosts the origin repository:

git config receive.denyDeleteCurrent true

Credit to the author of blog post http://www.mslinn.com/blog/?p=772

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ScottGuymer
  • 1,885
  • 1
  • 17
  • 22