tags:

views:

231

answers:

4

I have a repository in git. I made a branch, then did some changes both to the master and to the branch.

Then, tens of commits later, I realized the branch is in much better state than the master, so I want the branch to "become" the master and disregard the changes on master.

I cannot merge it, because I don't want to keep the changes on master. What should I do?

+3  A: 

Edit: You didn't say you had pushed to a public repo! That makes a world of difference.

There are two ways, the "dirty" way and the "clean" way. Suppose your branch is named new-master. This is the clean way:

git checkout new-master
git branch -m master old-master
git branch -m new-master master
# And don't do this part.  Just don't.  But if you want to...
# git branch -d --force old-master

This will make the config files change to match the renamed branches.

You can also do it the dirty way, which won't update the config files. This is kind of what goes on under the hood of the above...

mv -i .git/refs/new-master .git/refs/master
git checkout master
Dietrich Epp
Thank you. One more question. I am pushing it to github. What will happen on there, if I do this?
Karel Bílek
@Karel: It'll create a bit of a mess for other users; they'll have to reset their master to the github master. If you want to avoid causing them any trouble, have a look at my answer.
Jefromi
@Dietrick Epp: I'm not sure if it's a good idea to even suggest the dirty way. It's going to mess up remote tracking, reflogs... can't think of any reason you'd ever do it.
Jefromi
@Jefromi: If I want the branch named "master" to track some remote branch "master", the dirty way preserves this.
Dietrich Epp
@Dietrich Epp: Ah, that's a good point. You can have it both ways, though: `git branch old-master master; git branch -f master new-master`. Create the backup branch fresh, then directly move master to new-master. (And sorry for misspelling your name, just noticed that)
Jefromi
+1  A: 

Rename the branch to master by:

git branch -M branch_name master
Alan Haggai Alavi
+1  A: 

The solutions given here (renaming the branch in 'master') don't insist on the consequences for the remote (GitHub) repo:

  • if you hadn't push anything since making that branch, you can rename it and push it without any problem.
  • if you had push master on GitHub, you will need to 'git push -f' the new branch: you can no longer push in a fast forward mode.
    -f
    --force

Usually, the command refuses to update a remote ref that is not an ancestor of the local ref used to overwrite it. This flag disables the check. This can cause the remote repository to lose commits; use it with care.

If others have already pulled your repo, they won't be able to pull that new master history without replacing their own master with that new GitHub master branch (or dealing with lots of merges).
There are alternatives to a git push --force for public repos.
Jefromi's answer (merging the right changes back to the original master) is one of them.

VonC
+6  A: 

The problem with the other two answers is that the new master doesn't have the old master as an ancestor, so when you push it, everyone else will get messed up. This is what you want to do:

git checkout better_branch
git merge --strategy=ours master    # keep the content of this branch, but record a merge
git checkout master
git merge better_branch             # fast-forward master up to the merge

If you want your history to be a little clearer, I'd recommend adding some information to the merge commit message to make it clear what you've done. Change the second line to:

git merge --strategy=ours --no-commit master
git commit          # add information to the template merge message
Jefromi
I had the `merge --strategy=ours` linked in my answer, but not explicitly detailed, so... +1 to you ;)
VonC
this is it! thanks
Karel Bílek
@VonC: Oh, my bad. I skimmed your answer and didn't see it. Need to be more careful late at night.
Jefromi