ChatGPT解决这个技术问题 Extra ChatGPT

Make the current Git branch a master branch

git

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?

Extra: In this case, the 'old' master has already been push-ed to another repository such as GitHub. How does this change things?

Check answers to the very similar question stackoverflow.com/q/2862590/151641
Had a same problem, however I simply removed the master and renamed another branch to master: stackoverflow.com/a/14518201/189673
@jayarjo you should avoid this if you possibly can because it will rewrite history and cause problems for everyone else when they next try to pull master.

C
Cascabel

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

Note about git's merge "strategies": --strategy=ours is different from --strategy=recursive -Xours. I.e. "ours" can be a strategy in itself (result will be the current branch no matter what), or passed as an option to the "recursive" strategy (bring in other branch's changes, and automatically prefer current branch's changes when there's a conflict).
I had to make the second line git merge --strategy=ours master -m "new master" for it to work.
@Johsm That's exactly what the first sentence of my answer is talking about. If you do that, the new master will not have the same history as the old master, which is Very Bad if you want to push/pull. You need to have shared ancestry for that to work correctly; if instead you do what you're saying, then when you try to push it'll simply fail unless you force it (because this is Bad and it's trying to stop you), and if you do force it, then anyone who subsequently pulls will attempt to merge the old master and the new master, which will probably be a train wreck.
If vi editor during merge appears, type :w (for saving) :q (for exiting from vi)
This answer works great. I just wanted to add (for the people who may be new or unsure) that you'll have to do a git push right after this if you want your code pushed up to remote. You may see a warning like Your branch is ahead of 'origin/master' by 50 commits. This is expected. Just push it! :D
T
Trect

Make sure everything is pushed up to your remote repository (GitHub):

git checkout main

Overwrite "main" with "better_branch":

git reset --hard better_branch

Force the push to your remote repository:

git push -f origin main

This is probably the answer most people are looking for. All the other answers with the BS strategy merge do not replace the branch entirely. This made everything just like I wanted, simply overwrite the branch and push force it up.
although this is indeed what many are looking for, it should be noted that any other local copies of the repo will need to git reset --hard origin/master next time they want to pull, else git will try to merge the changes into their (now) divergent local. The dangers of this are explained more in this answer
please also note that you need to be allowed to force push to the repository - e.g in a business environment this won't work
The upside here can also be a downside depending on what people want. If you want to go as far as replacing the history of master with the history of the other branch, this is your answer.
This is the answer I was looking for, since my new branch was from master commit. This makes it easy for any branch from previous master not to have much merge issues.
D
Dietrich Epp

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

Thank you. One more question. I am pushing it to github. What will happen on there, if I do this?
@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.
@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.
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)
@FakeName I didn't conclude there was no reason to do it, just that there's no reason to do it the dirty way. You can do it using normal commands (as in my previous comment) and get the same result, except with reflogs intact and no chance of borking things. And it's guaranteed to work, since you're not mucking with implementation details.
A
Alan Haggai Alavi

Rename the branch to master by:

git branch -M branch_name master

Unfortunately git doesn't track branch renamings, so if you've already pushed your repo to a remote and others have local changes on their local old master branch, they will be in trouble.
is there a difference between this and git checkout master&&git reset --hard better_branch?
@thSoft What if it's only me that's using the repository?
P
Peter Mortensen

From what I understand, you can branch the current branch into an existing branch. In essence, this will overwrite master with whatever you have in the current branch:

git branch -f master HEAD

Once you've done that, you can normally push your local master branch, possibly requiring the force parameter here as well:

git push -f origin master

No merges, no long commands. Simply branch and push— but, yes, this will rewrite history of the master branch, so if you work in a team you have got to know what you're doing.

Alternatively, I found that you can push any branch to the any remote branch, so:

# This will force push the current branch to the remote master
git push -f origin HEAD:master

# Switch current branch to master
git checkout master

# Reset the local master branch to what's on the remote
git reset --hard origin/master

Very simple and worked perfectly! Two simple and easy to understand git commands. My git repo is saved and now looks super clean. Thanks!
@thehelix Why did you choose this solution when some of the higher-voted solutions (that were also there when you wrote your comment) are so much simpler?
T
Tomerikoo

I found the answer I wanted in the blog post Replace the master branch with another branch in git:

git checkout feature_branch
git merge -s ours --no-commit master
git commit      # Add a message regarding the replacement that you just did
git checkout master
git merge feature_branch

It's essentially the same as Cascabel's answer. Except that the "option" below their solution is already embedded in the above code block.

It's easier to find this way.

I'm adding this as a new answer, because if I need this solution later, I want to have all the code I need to use in one code block.

Otherwise, I may copy-and-paste, then read details below to see the line that I should have changed - after I already executed it.


P
Peeter Joot

I found this simple method to work the best. It does not rewrite history and all previous check-ins of branch will be appended to the master. Nothing is lost, and you can clearly see what transpired in the commit log.

Objective: Make current state of "branch" the "master"

Working on a branch, commit and push your changes to make sure your local and remote repositories are up to date:

git checkout master      # Set local repository to master
git reset --hard branch  # Force working tree and index to branch
git push origin master    # Update remote repository

After this, your master will be the exact state of your last commit of branch and your master commit log will show all check-ins of the branch.


C
Community

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.


M
Mo.

One can also checkout all files from the other branch into master:

git checkout master
git checkout better_branch -- .

and then commit all changes.


P
Pearson

To add to Cascabel's answer, if you don't want to place a meaningless merge in the history of the source branch, you can create a temporary branch for the ours merge, then throw it away:

git checkout <source>
git checkout -b temp            # temporary branch for merge
git merge -s ours <target>      # create merge commit with contents of <source>
git checkout <target>           # fast forward <target> to merge commit
git merge temp                  # ...
git branch -d temp              # throw temporary branch away

That way the merge commit will only exist in the history of the target branch.

Alternatively, if you don't want to create a merge at all, you can simply grab the contents of source and use them for a new commit on target:

git checkout <source>                          # fill index with contents of <source>
git symbolic-ref HEAD <target>                 # tell git we're committing on <target>
git commit -m "Setting contents to <source>"   # make an ordinary commit with the contents of <source>

a
ar-g

My way of doing things is the following

#Backup branch
git checkout -b master_backup
git push origin master_backup
git checkout master
#Hard Reset master branch to the last common commit
git reset --hard e8c8597
#Merge
git merge develop

P
Peter Mortensen

If you are using eGit in Eclipse:

Right click on the project node.

Choose Team → then Advanced → then Rename branch

Then expand the remote tracking folder.

Choose the branch with the wrong name, then click the rename button, rename it to whatever the new name.

Choose the new master, then rename it to master.


I did that but not sure whether it worked. On github, nothing changed but on git extensions I can see the branch were renamed.
k
knittl

For me, I wanted my develop branch to be back to the master after it was ahead.

While on develop:

git checkout master
git pull

git checkout develop
git pull

git reset --hard origin/master
git push -f

unrelated to the question asked
P
Peter Mortensen

The following steps are performed in the Git browser powered by Atlassian (Bitbucket server)

Making {current-branch} as master

Make a branch out of master and name it “master-duplicate”. Make a branch out of {current-branch} and name it “{current-branch}-copy”. In repository setting (Bitbucket) change “Default Branch” to point at “master-duplicate” (without this step, you will not be able to delete master - “In the Next step”). Delete “master” branch - I did this step from source tree (you can do it from the CLI or Git browser) Rename “{current-branch}” to “master” and push to repository (this will create a new “master” branch still “{current-branch}” will exist). In repository settings, change “Default Branch” to point at “master”.


A
Anuraag Barde

I know this is not what OP wanted, but you can do this if you know you will have a similar problem to OP in the future.

So here's your situation,

You need a branch that has new excellent new breaking features but is not prod currently. You have plans to make it prod in the future. Your current prod branch (master) is running fine but is boring. You might make some minor changes to it. You want to keep the current master (prod) branch safe for the future if later you need it.

If this feels confusing, see the below diagram of the bad situation.

*bad situation*
initial master   --->           added boring changes       ----merge---> you loose boring
            \                                                /
             ---> (awesome branch) added awesome changes ---

To solve this( i.e. to stop the loss of boring), do the following Basically,

Create a copy of your current master by doing git branch boring Replace boring with whatever name you want to keep Now, you can add new awesome features to your master branch and add boring features to the boring branch. You can still keep updating the boring branch and maybe use it to never merge it to master. You will not lose the boring features. Your master branch will have awesome features.

So,

*good situation*
 initial master   --->     added awesome changes     --->    Final master(awesome) branch
                \
                 --->   (boring branch) added boring changes  ---> Dont merge to master  --X-->

Can you please change copy and paste your code into code blocks rather than using screenshot images? It's considered bad practice to use screenshots (it's less searchable, can't be read by software for the blind, can't be copy-pasted, etc.)
@user1271772 I actually tried doing that instead of taking images (that's why the content of the image is in ascii), but stackoverflow messed up the words, if viewed in a mobile/smaller device, it would not make any sense. Thats why I decided to keep it in an image form. Thanks for the intimation though.
It looks the same, except for and extra --X--> in this version compared to the screenshot. Which words are messed up?
It looks like it worked. There was some issue with inserting a code block after an ordered list. Some trial and error involving whitespace fixed that up. Thanks again.
Yea I guess you had to add the so to it. I was the one that gave you the +1 when you had -1, so I can't upvote again, but thanks for fixing it.
T
Tanmay Shrivastava

Just go to the gitlab or github website and find for settings.

Then under settings find for repository.

There find for default branch, expand it and you can get the options to rename it or change it to other branch.

I tried this in gitlab and it worked.


u
user37216

I'm surprised this isn't an answer here. This is what I did.

Made 2 copies of the repo in my filesystem in different directories, one with master and one with the branch. Copied (manually) all files from the branch to master Committed the changes to master.

This way, there is a single commit with all the differences included, the commit history is preserved, and no hard force pushes are required.