git push --force-with-lease vs. --force


182

我试图了解两者之间的区别

git push --force

git push --force-with-lease

我的猜测是,如果远程没有本地分支没有的提交,则后者仅推送到远程?


“本地远程跟踪分支 ”。从根本上说,遥控器必须看起来像客户希望的样子。 git help push有用例说明了其目的(基本上是为了防止您浪费别人刚刚提出的变更)。我有点不清楚远程跟踪分支的工作方式。但大概通常情况下,您需要准确查看上次执行fetchpull没有新提交时的外观。
zzxyz

4
@zzxyz:的实际实现--force-with-lease与现代CPU上的比较和交换指令的实现类似:希望发生交换的提供了期望值和新值。进行交换的系统将期望值与真实的当前值进行比较,并且当且仅当两者相等时才进行交换。使用git push,期望值就是远程跟踪名称中的值,例如,git push --force-with-lease origin X将您自己的origin/X值与新的期望值一起发送;origin的Git会告诉您是否进行了交换。
torek

1
如果Git at origin进行了交换,那么您就完成了。如果不是,您可以运行git fetch origin以获取新的当前值,如果需要,可以对所做的更改进行重新处理,然后运行另一个“租赁租用比较交换”以再次尝试。
torek

Answers:


172

force 用您的本地分支覆盖远程分支。

--force-with-lease是一个更安全的选项,如果有更多提交(由另一个团队成员或同事或您拥有的东西)添加到远程分支,则不会覆盖远程分支上的任何工作。这样可以确保您不会通过强行覆盖其他人的工作。

我认为您对命令的总体了解是正确的。如果远程分支与本地计算机上的远程分支具有相同的值,则将覆盖远程。如果没有相同的值,则表示您在处理代码时其他人对远程分支进行了更改,因此不会覆盖任何代码。显然,如果远程有其他提交,则值将不同。

我只是想--force-with-lease作为确保不覆盖任何队友代码的选项。我公司的许多团队都将其--force-with-lease用作故障保险的默认选项。它在大多数情况下是不必要的,但是如果您碰巧覆盖了另一个人贡献给远程用户的内容,则将为您节省很多头痛。

我确定您查看了这些文档,但此处可能包含一些更冗长的解释:

https://git-scm.com/docs/git-push


38

寻找来自可靠和/或官方来源的答案。

Git本身来源进一步说明了torek评论他的其他答案中提到的“比较和交换” 。

后者仅在远程没有本地分支没有提交的提交时才推送到远程吗?

此提交中引入了功能(2013年12月,Git v1.8.5-rc0)

--force-with-lease 除非另有说明,否则将通过要求它们的当前值与某个合理的默认值相同来保护所有将要更新的远程引用;

现在,暂时将“某个合理的默认值”定义为“ 我们为正在更新的远程服务器提供的远程跟踪分支的值 ”,如果我们没有这样的远程跟踪分支,那就是错误的。

因此,“租赁”是指:

force-with-lease”:您假设在获取引用以确定参考的历史记录时已在ref上获得了租约,并且只有在租约未中断的情况下才可以回退。

消息来源仍然提到“ cas”:

  • 此选项最初称为“ cas”(用于“比较和交换”),因为它太技术性,所以没人喜欢。
  • 第二次尝试将其称为“ lockref”(因为从概念上讲,它类似于在获取锁定后进行推送),但讨厌“ lock”一词是因为它暗示它可能会拒绝其他人的推送,这不是此选项的工作方式。
  • 这一回合称其为“租赁用力”。
    您假定在获取时决定是否在ref上租用了ref,以决定重新建立的历史记录应该是什么,并且只有在未破坏租约的情况下才可以回退。

因此:“ git push --force-with-lease--force

正如我在Git 2.13(2017年第二季度)中提到的“ push --force-with-lease默认情况 ”中提到的那样,如果运行了后台进程(例如在带有Git插件的IDE中找到的进程),--force-with-lease则可以忽略该选项git fetch origin
在这种情况下,--force占优势。


29

git push --force具有破坏性,因为它无条件地用本地存储库覆盖远程存储库。强烈建议不要使用git的push --force,因为它可以破坏已经推送到共享存储库的其他提交。强制推送最常见的原因之一是当我们被迫重新设置分支的基础时。

例如。我们有一个带有功能分支的项目,爱丽丝和鲍勃都将从事这项工作。他们都克隆该存储库并开始工作。Alice最初完成了该功能的一部分,并将其推入主存储库。这一切都很好。鲍勃也完成了他的工作,但是在推高工作之前,他注意到一些更改已合并到母版中。为了保持一棵干净的树,他对master分支进行了rebase。当然,当他去推动这个重新组织的分支时,它将被拒绝。但是他没有意识到爱丽丝已经推动了她的工作,而是执行了推力。不幸的是,这将删除中央存储库中有关Alice更改的所有记录。

什么--force-与租赁确实是垃圾更新某个分支,除非它是我们所期望的状态; 即没有人更新上游分支。在实践中,这是通过检查上游ref是否符合我们的期望来实现的,因为ref是散列,并将父链隐式地编码为其值。

是有关git push --force和git push --force-with-lease的好帖子。


2
我不明白的是-如果您以master为基础,那么您应该可以不使用 --force-with-lease--force-with-lease与大师重新定级后为什么有必要?
亚历山大·米尔斯

3
@AlexanderMills可能有引起问题的可能性。如果您是最后一位掌握此知识的人,那么没有问题,但是还有其他人在从事其他任务,那么这可能会导致严重的问题。首先说A-B-C是主人,首先是爱丽丝将其命名为A-B-C-D-E,而鲍勃则将其命名为A-B-C-F-G。如果爱丽丝是最后一个推动者在重新设置A-B-C-D-E-F-G后不会出现任何问题,但另一个人Tom会在主灾难中同时尝试推A-B-C-D-E-R! !
沙基尔

3
--force不会丢失提交,只会将它们分离。可以通过使用哈希来恢复它们,如git checkout <SHA>或中所述git reset --hard <SHA>,假设远程仓库的维护者不执行任何GC或修剪操作。
基思·罗素

1
“强烈建议不要使用git的push --force,因为它可能破坏已经推送到共享存储库的其他提交”。此声明强烈基于意见。强制执行是正常git rebase代码检查工作流程的一部分。同样像已经提到的,即使执行此操作,您也可以检索提交。
艾蒂安

9

假设服务器上的任何预接收挂钩都接受推送,则此操作将始终成功:

git push --force

鉴于此在继续之前运行特定的客户端检查:

git push --force-with-lease

您可以自己手动运行特定检查。这是“租赁检查”算法:

  1. 找出您当前的分支。

  2. 运行git for-each-ref refs/remotes。注意git客户端认为与当前分支的上游状态相对应的commit-id。

例如,如果您在分支“ foo”上,请注意与“ refs / remotes / origin / foo”关联的提交ID。

  1. 现在确定上游git服务器上远程分支的实际提交ID。

  2. 如果您从步骤2和步骤3中提取的提交ID一致,则仅让“ git push”继续进行。换句话说,只有在本地git克隆的上游概念与实际上游一致的情况下,才可以继续操作。

这里有一个可悲的含义:由于将git fetch“ refs / remotes / origin / *”下的所有ref更新为最新版本,因此这种命令组合基本上与git push --force

git fetch

# The command below behaves identically to "git push --force"
# if a "git fetch" just happened!

git push --force-with-lease

为了解决这种固有的弱点,git push --force-with-lease我尝试永远不要跑步git fetch。取而代之的是,我总是git pull --rebase在需要与上游同步时始终运行,因为它git pull仅更新ref / remotes下的单个ref,从而保持--force-with-lease有用的“租约” 。


1
如果支票是在客户端,是否有竞争条件的可能性?即有人在检查之后但在强制推送之前推送更改吗?
craq

2

租赁强制不一定安全。正如西尔维(Sylvie)所说。注意事项:在git中,分支只是提交的指针。并且提交指向零个或多个父提交。即使您使用硬git reset和强制推送或使用--force-with-lease完全不希望地改变了分支,也不一定是大问题。您可以使用本地git reflog查看分支上的本地提示(当时HEAD在哪里?)并重置并再次推动分支。这样,您只会丢失远程分支上的新提交,但即使是团队成员也可能将其还原。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.