强制“git push”覆盖远程文件

Force “git push” to overwrite remote files

我想推送本地文件,并将它们放在远程回购上,而不必处理合并冲突。我只想让我的本地版本优先于远程版本。

我怎么能用Git做到这一点?


您应该能够通过使用

1
git push -f <remote> <branch>

(如git push -f origin master)。离开将迫使设置--set-upstream的所有地方分支机构。

请注意,如果其他人共享此存储库,他们的修订历史将与新存储库发生冲突。如果他们在变更点之后有任何本地提交,他们将变得无效。

更新:我想我会添加一个旁注。如果您正在创建其他人将审查的更改,那么使用这些更改创建一个分支并定期重新调整它们以使其与主开发分支保持最新,这并不少见。只需让其他开发人员知道这将定期发生,这样他们就知道会发生什么。

更新2:由于越来越多的观众,我想添加一些额外的信息,说明当你的upstream确实遇到了强制推送时该怎么做。

假设我克隆了您的回购,并添加了一些这样的承诺:

1
2
3
            D----E  topic
           /
A----B----C         development

但是后来,development分支被rebase攻击,这将导致我在运行git pull时收到这样的错误:

1
2
3
4
5
6
Unpacking objects: 100% (3/3), done.
From <repo-location>
 * branch            development     -> FETCH_HEAD
Auto-merging <files>
CONFLICT (content): Merge conflict in <locations>
Automatic merge failed; fix conflicts and then commit the result.

在这里,我可以解决冲突和commit,但这会给我留下一个非常丑陋的承诺历史:

1
2
3
       C----D----E----F    topic
      /              /
A----B--------------C'  development

使用git pull --force可能看起来很诱人,但要小心,因为这样会使您陷入困境:

1
2
3
            D----E   topic

A----B----C'         development

所以最好的选择可能是做一个git pull --rebase。这将要求我像以前那样解决任何冲突,但对于每一步,我将使用git rebase --continue,而不是承诺。最后,提交历史看起来会更好:

1
2
3
            D'---E'  topic
           /
A----B----C'         development

更新3:你也可以使用--force-with-lease选项作为"更安全"的部队按,正如他的纸杯蛋糕所提到的回答:

Force pushing with a"lease" allows the force push to fail if there
are new commits on the remote that you didn't expect (technically, if
you haven't fetched them into your remote-tracking branch yet), which
is useful if you don't want to accidentally overwrite someone else's
commits that you didn't even know about yet, and you just want to
overwrite your own:

1
git push <remote> <branch> --force-with-lease

You can learn more details about how to use --force-with-lease by
reading any of the following:

  • git push documentation
  • Git: How to ignore fast forward and revert origin [branch] to earlier commit?


你想用力推

您基本上想要做的是强制推送您的本地分支,以便覆盖远程分支。

如果您想要更详细地解释以下每个命令,请参阅下面的"我的详细信息"部分。你基本上有4个不同的选择来强制推Git:

1
2
3
4
5
6
7
8
9
git push <remote> <branch> -f
git push origin master -f # Example

git push <remote> -f
git push origin -f # Example

git push -f

git push <remote> <branch> --force-with-lease

如果您想要更详细地解释每个命令,请参阅下面的"我的长答案"部分。

警告:强制推送将用正在推送的分支的状态覆盖远程分支。在使用之前,请确保这是您真正想要做的,否则您可能会覆盖您实际想要保留的提交。

强制推送详细信息指定远程和分支

您可以完全指定特定的分支和远程。-f标志是--force的短版本。

1
2
git push <remote> <branch> --force
git push <remote> <branch> -f

号省略分支

如果省略了要推分支的分支,Git将根据您的配置设置来计算它。在2.0之后的Git版本中,新回购将具有默认设置以推送当前签出的分支:

1
git push <remote> --force

而在2.0之前,新的repos将具有推送多个本地分支的默认设置。所讨论的设置是remote..pushpush.default设置(见下文)。

省略远程和分支

如果同时忽略了远程和分支,则只有git push --force的行为由您的push.defaultgit配置设置决定:

1
git push --force

  • 从Git2.0开始,默认设置simple基本上将把当前分支推到其上游远程计数器部分。远程由分行的branch..remote设置决定,否则默认为原始回购。

  • 在Git2.0之前,默认设置matching基本上只是将所有本地分支推送到远程(默认为源站)上同名的分支。

通过阅读git help config或git config(1)手册的在线版本,您可以阅读更多的push.default设置。

使用--force-with-lease更安全地用力推动

使用"租约"强制推送允许强制推送失败,前提是远程上有您不期望的新提交(从技术上讲,如果您还没有将它们提取到远程跟踪分支中),如果您不想意外覆盖您甚至还不知道的其他人提交,并且您只想覆盖自己动手:

1
git push <remote> <branch> --force-with-lease

通过阅读以下内容,您可以了解有关如何使用--force-with-lease的更多详细信息:

  • git push文件
  • Git:如何忽略fast forward并将origin[branch]恢复为早期提交?


另一个选择(为了避免任何对其他参与者有问题的强制推送)是:

  • 把你的新承诺放到一个专门的分支中
  • origin/master上重置master
  • 将您的专用分支合并到master,始终保持来自专用分支的承诺(即在master之上创建新的修订,这将反映您的专用分支)。关于模拟git merge --strategy=theirs的策略,请参见"git command for making one branch like another"。

这样,您就可以将master推到远程,而无需强制执行任何操作。


git push-f有点破坏性,因为它重置了团队中其他人所做的任何远程更改。一个更安全的选择是Git Push——强制租赁。

——强制租赁所做的是拒绝更新分支,除非它是我们期望的状态;即没有人更新上游分支。实际上,这是通过检查上游引用是否是我们期望的,因为引用是散列,并将父链隐式编码为其值。您可以确切地告诉--force with lease检查什么,但默认情况下会检查当前的远程引用。这在实践中意味着,当Alice更新其分支并将其推送到远程存储库时,分支的引用指向头将被更新。现在,除非Bob从遥控器中提取数据,否则他对遥控器的本地引用将过时。当他使用——带租约强制执行进行推送时,Git将对照新远程检查本地引用,并拒绝强制执行推送。——强制租用有效地只允许您在没有其他人将更改推送到远程的情况下强制推送。系好安全带,用力。