如何在Git中完全从另一个分支替换主分支?

2108

我在我的Git存储库中有两个分支:

  1. master
  2. seotweaks(最初从master创建)

我创建seotweaks的目的是快速将其合并回master。然而,三个月过去了,这个分支中的代码已经比master高13个版本。

现在它已经成为我们的主要工作分支,因为master中的所有代码现在或多或少都已经过时了。

我知道这样做非常不好,已经吸取教训了。

你知道如何将master分支中的所有内容替换为seotweaks中的内容吗?

我可以删除master中的所有内容并进行合并,但这似乎不是最佳实践。


46
关于“完全重复”的标记 - 这可能是真的,但我认为下面Ergosys的回答比那个问题的被接受回答更好。 - mikermcneil
33
请注意,这篇文章可能会被标记为重复,但它是在网络搜索“git delete branch master”中的第一个结果。 - peterk
35
这些观点很少对专注于复制品的狂热者有任何影响。 - geotheory
3
这个问题的措辞更好,而且没有因回答开始后添加的“额外”评论而引起混淆。 - Rob Osborne
你也可以检查这个解决方案 https://dev59.com/YnI_5IYBdhLWcg3wF_F3#3790682 - Salma Gomaa
如果您不担心 seotweaks 的提交历史记录,那么有一种简单的方法,可以使用 checkout。首先切换到主分支,然后运行以下命令:git checkout seotweaks -- *接下来运行:git commit -m "Replaced contents of master with seotweaks"最后运行git push - learner
5个回答

3551

您应该能够使用“ours”合并策略,以这种方式覆盖主分支与SEO优化:

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

前两步是为了确保你本地的主分支副本是最新的有用预防措施。结果应该是你的主分支现在基本上是seotweaks。

(-s ours--strategy=ours的缩写)

文档关于“ours”策略:

这解决了任意数量的头,但合并的结果树总是当前分支头的树,有效地忽略了所有其他分支的更改。它旨在用于取代侧分支的旧开发历史。请注意,这与递归合并策略的-Xours选项不同。

更新评论:如果出现致命错误:refusing to merge unrelated histories,则将第二行更改为:git merge --allow-unrelated-histories -s ours master


51
可能有点晚了,但这句话有什么问题: git checkout master;git merge -s theirs seotweaks - 能够省去几个步骤。 - Subu Sankara Subramanian
5
@Subu Subramanian,没有这样的选项。请参阅http://repo.or.cz/w/git.git/blob/HEAD:/Documentation/merge-strategies.txt。 - ergosys
39
@Joel Berger,递归合并选项将混合两个分支,在冲突时仅优先选择“theirs”或“ours”。因此,您将获得来自两个分支的更改。 - ergosys
47
这对我来说行不通。当我在另一个分支上运行“git merge -s ours master”时,会显示“Already up-to-date.”。还有其他什么尝试的方法吗? - elsurudo
17
如果你遇到了 fatal: refusing to merge unrelated histories 的错误提示,那么将第二行改为:git merge --allow-unrelated-histories -s ours master - code4kix
显示剩余38条评论

630

使用git branch -m命令将主分支重命名为其他名称,然后将seotweaks分支重命名为主分支,这个方法怎么样?像这样:

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

这可能会删除 origin master 中的提交记录,在运行git push -f origin master之前,请先检查您的 origin master。


38
尝试使用命令 git push -f origin master 进行推送。 - Koraktor
11
确保您的主分支可以完全替换后,这可能是进行强制更新的最佳方法。 - Hrishi
18
值得说明的是,这个答案可能会删除原始的 master 分支中存在的提交记录。而 ergosys 的解决方案执行了正确的合并操作,因此保留了 master 分支的所有历史记录。 - florisla
57
糟糕,我刚刚在原始主分支中丢失了所有提交。 - moberme
5
您可以执行 git checkout old-master && git push origin old-master 命令创建一个旧主分支。 - Sander Visser
显示剩余11条评论

89
你可以在远程重命名/删除主分支,但如果很多人基于远程主分支进行工作并将该分支拉入其本地仓库,则这将是一个问题。由于每个人似乎都在 'seotweaks' 分支上工作,因此可能不是这种情况。
在这种情况下,您可以执行以下操作: git remote show 可能无法正常工作。 (执行 git remote show 以检查如何在本地仓库中声明您的远程仓库。我将假设 'origin') (关于 GitHub,house9 评论说:“我还需要执行一步操作,在 GitHub 上点击 'Admin' 按钮,并将 'Default Branch' 设置为除 'master' 以外的其他内容,然后再将其放回”)
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

但是:

  • 如果其他用户在主分支在远程被删除时尝试拉取,他们的拉取将失败("no such ref on remote")
  • 当远程重新创建master时,拉取将尝试将新的master合并到他们本地(旧的)master上:会出现许多冲突。实际上,他们需要将本地的master重置为他们将要获取的remote/master分支,并忘记他们当前的master

更新/注释 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

感谢您的详细回复。当我运行“git push remote :master”时,出现错误 - “remote”似乎不是git存储库。 - Jason
@Jason:我把它改成了“origin”,这可能是给你的远程仓库默认命名。 - VonC
1
@VonC:我正在尝试在git-hub存储库上进行操作,但是当我尝试执行“git push origin:master”时,我收到一条消息:“[remote rejected] master (deletion of the current branch prohibited)”。至于为什么我这样做...基本上我严重混淆了事情,通过github界面和命令行推送两次相同的补丁,然后通过手动合并使一切恢复正常。之后,我还创建了另一个具有干净历史记录的分支,但太晚了...无论如何。由于它在我的个人实验性存储库中,所以只会影响我自己。 - kriss
5
GitHub默认拒绝重写/删除历史记录的推送,除非你强制推送:git push -f origin:master。请注意,翻译没有改变原意,只是将其简化为通俗易懂的表达方式。 - VonC
4
谢谢,这帮了我很大的忙;我还需要执行一个额外的步骤,在 GitHub 上点击“管理”按钮,并将“默认分支”设置为除“master”以外的其他分支,然后再将其改回来。 - house9
@house9:说得好。我已经编辑了我的答案,包括那一步。 - VonC

50

因为 seotweaks 最初是从 master 分支创建的,将其合并回去是一个好主意。不过,如果你的某个分支不是真正从 master 衍生出来的,或者你的历史记录非常不同,你只想放弃 master 分支,转而使用你一直在开发工作的新分支,那么可以这样做:

git push [-f] origin seotweaks:master

如果你遇到了下面这个错误,这尤其有帮助:

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

你并没有使用GitHub,也无法访问“管理”选项卡来更改远程存储库的默认分支。此外,这不会导致删除主分支时可能遇到的停机时间或竞争条件:

git push origin :master

无法在Heroku上工作:![rejected] <new_branch> -> master(非快进) 错误:未能将一些引用推送到'<some_git>.git'。 - shaioz
3
git push -f origin seotweaks:master 对我有效。 - Tom Andersen
1
这绝对是我在一个工作分支上进行广泛更改的最简单方法,因为有许多困难的冲突(由于文件夹被删除和重命名)。我不知道这是否适用于每种情况(可能不是),但它完全适用于我,只需将我完成的所有内容从分支中取出并放回主分支(操作后,工作分支仍然存在,但两个分支似乎现在具有相同的提交)。 - Ben Stahl
force pushmaster git 历史记录会是什么样子?即使在 seotweaks 上没有更改,它是否会覆盖 master 上的所有文件? - BartusZak

8

我发现这是最好的方法(我的服务器不允许我删除文件)。

在托管origin仓库的服务器上,在仓库内的某个目录下键入以下命令:

git config receive.denyDeleteCurrent ignore

在你的工作站上:

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

回到托管 origin 仓库的服务器:

git config receive.denyDeleteCurrent true

感谢博客文章作者http://www.mslinn.com/blog/?p=772

的贡献。


对我来说,“master”分支是默认分支,所以我将默认分支更改为“develop”分支,然后删除了“master”分支,并从所需的分支再次创建了“master”分支。以后如果需要,您可以再次将“master”分支设置为默认分支。 - Sharad
链接已经损坏,出现了“拒绝访问”的错误提示。 - Peter Mortensen
遗憾。我认为他的网站上仍然存在博客,只是链接失效了 :( - ScottGuymer
它已经改变了。现在它显示帖子的索引(它们似乎是可访问的)。 - Peter Mortensen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接