我在Git中有一个代码库。我创建了一个分支,然后对主干和分支都进行了一些更改。
然后经过数十次提交后,我意识到该分支比主干更好,所以我想让该分支“成为”主干并忽略主干上的更改。
我不能合并它,因为我不想保留主干上的更改。我该怎么办?
额外信息:在这种情况下,“旧”的主干已经被推送到其他存储库,如GitHub。这会改变什么吗?
我在Git中有一个代码库。我创建了一个分支,然后对主干和分支都进行了一些更改。
然后经过数十次提交后,我意识到该分支比主干更好,所以我想让该分支“成为”主干并忽略主干上的更改。
我不能合并它,因为我不想保留主干上的更改。我该怎么办?
额外信息:在这种情况下,“旧”的主干已经被推送到其他存储库,如GitHub。这会改变什么吗?
另外两个答案存在的问题是,新的主分支没有旧的主分支作为祖先,因此当你推送它时,其他人会混乱。以下是您要执行的操作:
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
如果您希望您的历史记录更加清晰,我建议在合并提交消息中添加一些信息,以使清楚地了解您所做的事情。将第二行更改为:
git merge --strategy=ours --no-commit master
git commit # add information to the template merge message
--strategy=ours
与 --strategy=recursive -Xours
是不同的。也就是说,“ours” 可以作为一种独立的策略(无论如何都会得到当前分支的结果),或者作为 "recursive" 策略的选项(引入其他分支的更改,并在冲突时自动优先采用当前分支的更改)。 - Kelvingit merge --strategy=ours master -m "new master"
。 - incandescentmangit push
命令。你可能会看到一个警告,如“Your branch is ahead of 'origin/master' by 50 commits.”这是正常现象,只需点击推送即可! :D - chapeljuice确保将所有内容推送到您的远程仓库(GitHub):
git checkout main
使用"better_branch"覆盖"main"分支:
git reset --hard better_branch
强制推送到远程仓库:
git push -f origin main
git reset --hard origin/master
,否则 git 将尝试将更改合并到它们(现在)不同的本地副本中。这种情况的危险性在这个答案中有更详细的解释。 - 7yl4r编辑:你没说过你已经推送到公共仓库!这可是天壤之别。
有两种方法,一种是“脏”的方式,另一种是“干净”的方式。假设你的分支名为new-master
,这是干净的方式:
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
这将使配置文件更改以匹配重命名的分支。
您还可以采用“肮脏”的方式,不会更新配置文件。这有点像上面的操作...
mv -i .git/refs/new-master .git/refs/master
git checkout master
git branch old-master master; git branch -f master new-master
。创建备份分支,然后直接将主分支移动到新的主分支。 (对于拼错你的名字,我感到抱歉,刚刚才注意到) - Cascabel通过以下方式将分支重命名为master
:
git branch -M branch_name master
git checkout master && git reset --hard better_branch
有什么区别吗? - wotanii据我所知,您可以将当前分支分支到现有分支。本质上,这将使用当前分支中的内容覆盖master
:
git branch -f master HEAD
完成上述步骤后,你通常可以推送本地的 master
分支,可能也需要在此处使用 force 参数:
git push -f origin master
没有合并,也没有长命令。只需使用branch
和push
命令。但是,是的,这将重写master
分支的历史记录,所以如果你在团队中工作,你必须知道自己在做什么。
或者,我发现你可以将任何分支推送到任何远程分支,所以:
# 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
我在博客文章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
基本上与Cascabel的回答相同。只是他们解决方案中的"选项"在上面的代码块中已经嵌入。
这样更容易找到。
我将其作为新答案添加,因为如果我以后需要此解决方法,我希望在一个代码块中拥有所有需要使用的代码。
否则,我可能会复制粘贴,然后在执行代码之后才发现应该更改的行 - 之后才阅读下面的详细信息。
我发现这种简单的方法效果最好。它不会重写历史记录,分支的所有先前提交将附加到主分支上。没有任何损失,您可以在提交日志中清楚地看到发生了什么。
目标:使当前“branch”的状态成为“master”
在分支上工作,提交并推送更改以确保本地和远程存储库是最新的:
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
完成后,您的主分支将与上一次提交所在的分支状态完全相同,并且您的主分支提交日志将显示该分支的所有检入记录。
这里提供的解决方案(在“主”分支中重命名分支)并不强制执行对远程(GitHub)仓库的后果:
-f --force
通常,该命令会拒绝更新不是用来覆盖它的局部参考的祖先的远程参考。此标记禁用了检查。这可能导致远程存储库丢失提交;请谨慎使用。
如果其他人已经拉取您的存储库,则无法拉取新的主分支历史记录,除非将其自己的主分支替换为该新GitHub主分支(或处理大量合并)。
有公共存储库的git push --force可替代方案。
Jefromi的回答(将正确的更改合并回原始主分支)是其中之一。
你也可以将另一个分支的所有文件检出到主分支:
git checkout master
git checkout better_branch -- .
然后提交所有更改。
补充一下Cascabel的回答,如果您不想在source
分支的历史记录中留下一个无意义的合并,您可以为ours
合并创建一个临时分支,然后将其丢弃:
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
这样合并提交将仅存在于目标分支的历史记录中。
或者,如果您根本不想创建合并,则可以简单地获取“源”内容并将其用于“目标”的新提交:
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>