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

时间:2018-10-15 19:42:47

标签: git git-push

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

git push -f

git push --force-with-lease

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

如果有一个更好的方式来表达问题,即lmk,但希望它很清楚。

5 个答案:

答案 0 :(得分:12)

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

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

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

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

我确定您已经看过文档,但是这里可能包含一些冗长的解释:

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

答案 1 :(得分:7)

  

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

torek暗示了the commentshis other answersources of Git itself中提到的“比较和交换”。

  

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

commit 28f5d17中引入了该功能(2013年12月,Git v1.8.5-rc0)

  

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

     

目前,“一些合理的默认值”被临时定义为“ 远程更新的远程跟踪分支的值”,如果我们将其设置为错误,没有这样的远程跟踪分支。

“租赁”的意思是:

  

“ {force-with-lease”:您假设在获取数据以决定重新记录的历史记录时已在ref上获得了租约,并且只有在租约未中断的情况下才可以撤回。

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

  
      
  • 此选项最初被称为“ cas ”(用于“比较和交换”),这个名字由于技术性太强而没有人喜欢。
  •   
  • 第二次尝试将其称为“ lockref”(因为从概念上讲,它类似于在获取锁定后进行推送),但讨厌“ lock”一词是因为它暗示它可能会拒绝其他人的推送,而这不是此选项的工作方式。
  •   
  • 本轮比赛称为“租赁强制”。
      您假设在获取数据来决定重新记录的历史记录时应该在ref上租借,并且只有在   租约没有被破坏。
  •   

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

正如我在“ push --force-with-lease by default”中提到的,正如Git 2.13(2017年第二季度)所提到的,如果后台进程(例如那些您在带有Git插件的IDE中发现)运行--force-with-lease
在这种情况下,以git fetch origin为准。

答案 2 :(得分:7)

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

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

-带租用的功能是拒绝更新分支,除非它是我们期望的状态。即没有人更新上游分支。在实践中,这是通过检查上游引用是否符合我们的期望来实现的,因为引用是散列,并且将父链隐式地编码为其值。

Here是有关git push --force和git push --force-with-lease的不错的帖子。

答案 3 :(得分:2)

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

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 clone的上游概念与实际上游一致的情况下,才能继续操作。

这里有一个可悲的含义:由于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仅在引用/远程处理下更新单个引用,从而使--force-with-lease的“租赁”保持有用。

答案 4 :(得分:2)

强制租赁不一定安全。就像西尔维(Sylvie)所说的那样。注意事项:在git中,分支只是提交的指针。并且提交指向零个或多个父提交。即使您完全通过硬git reset和强制推送或带有--force-with-lease的推送完全更改了分支,而又不想这么做,也不一定是大问题。您可以使用本地git reflog查看分支上的本地提示(当时HEAD在哪里?)并重置并再次推动分支。然后,您只会丢失远程分支上的新提交,但即使是团队成员也可以将其恢复。