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

Ale*_*lls 87 git git-push

我试图了解它们之间的区别

git push -f
Run Code Online (Sandbox Code Playgroud)

git push --force-with-lease
Run Code Online (Sandbox Code Playgroud)

我的猜测是,如果遥控器没有本地分支没有的提交,后者只会推送到遥控

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

che*_*bow 61

force 用本地分支覆盖远程分支.

--force-with-lease如果将更多提交添加到远程分支(由另一个团队成员或同事或您有什么),则更安全的选项不会覆盖远程分支上的任何工作.它确保您不会通过强制推动覆盖某些人的工作.

我认为围绕命令的一般想法是正确的.如果远程分支具有与本地计算机上的远程分支相同的值,则将覆盖远程分支.如果它没有相同的值 - 它表示在您处理代码时其他人对远程分支所做的更改,因此不会覆盖任何代码.显然,如果远程中有其他提交,则值将不相同.

--force-with-lease当我想确保不覆盖任何队友代码时,我只想到使用的选项.我公司的许多团队都使用--force-with-lease故障安全的默认选项.在大多数情况下它是不必要的,但是如果你碰巧覆盖了另一个人为远程做出贡献的事情,那将会给你带来很多麻烦.

我确定你看过这些文档,但这里可能还有一些罗嗦的解释:

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

  • 这个答案没有意义,因为你不能在 Git 中“覆盖代码”。也许您的意思是它不会使其他人的提交变得无法访问?但它甚至不这样做。 (6认同)
  • @sKopheK 对于您的情况来说可能为时已晚,但是 --force-with-lease 的优点是,即使您从远程分支(有意或无意)删除了提交,它们也已经在您的本地存储库中,您可以重置分支再次通过reflog。这意味着即使“如果”出现问题,也可以更轻松地回滚并在几秒钟内再次强制推送,很可能在任何人受到影响之前(如果您意识到并立即修复它)。 (2认同)

Sha*_*kil 19

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

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

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

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

  • @AlexanderMills 可能有一些导致问题的可能性。如果您是最后一个将其推到掌握的人,那么没问题,但有另一个人在处理另一项任务,则可能会导致严重的问题。假设一开始 A - B - C 是在 master 中,首先 Alice 让它成为 A - B - C - D - E,同时 Bob 让它成为 A - B - C - F - G。如果 Alice 是最后一个推动的人在主 A - B - C - D - E - F - G 变基后不会造成任何问题,但另一个人 Tom 尝试同时推 A - B - C - D - E - R 会发生主灾难! ! (3认同)
  • `--force` 不会丢失提交,它只是将它们分离。它们可以通过哈希值复活,如“git checkout <SHA>”或“git reset --hard <SHA>”,假设远程存储库的维护者不执行任何 GC 或修剪操作。 (3认同)
  • 我不明白的是-如果您使用 master 进行变基,那么您应该能够*而无需*`--force-with-lease`?为什么在与 master 重新绑定后需要`--force-with-lease`? (2认同)
  • “强烈建议不要使用 git 的 Push --force,因为它可能会破坏已推送到共享存储库的其他提交”,此声明强烈基于意见。强制推送是正常 git rebase 代码审查工作流程的一部分。就像已经提到的那样,即使在执行此操作之后,您也可以检索提交。 (2认同)

Von*_*onC 16

寻找可信和/或官方来源的答案.

评论他的另一个答案中,torek提到的"比较和交换"被Git本身来源进一步说明了.

如果远程没有本地分支没有的提交,后者只会推送到远程?

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

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

目前,"一些合理的默认值"暂时定义为" 我们对远程更新的ref的远程跟踪分支的值 ",如果我们没有这样的远程跟踪分支则是错误的.

所以"租约"意味着:

" force-with-lease":当你决定重新定义历史应该是什么时,你假设你在ref上接受了租约,并且只有在租约没有被破坏时你才可以退回.

消息来源仍然提到"cas":

  • 这个选项最初被称为" cas"(用于"比较和交换"),这个名称没有人喜欢,因为它太技术性了.
  • 第二次尝试称它为"lockref"(因为它在概念上就像是在锁定后推动)但是"锁定"这个词是令人讨厌的,因为它暗示它可能拒绝别人的推动,这不是这个选项的工作方式.
  • 这轮称它为"强制租赁".
    你假设你在决定重新定义历史应该是什么时接受ref的租约,并且只有在租约没有被破坏时你才可以退回.

所以:" git push --force-with-lease对战--force"

正如我在" push --force-with-lease默认情况下 "中提到的那样,正如Git 2.13(2017年第2季度)提到的那样,如果后台进程(比如你在带有Git插件的IDE中找到的进程)运行,则--force-with-lease可以忽略该选项git fetch origin.
在这种情况下,--force占上风.

  • 关于最后一段的更正:它本身并没有被忽略,只是现在你对本地远程头和远程头有相同的引用,所以 `--force-with-lease` 将表现正确 - 比较这两个,如果在在获取和推送之间的时间间隔,有人更新了远程,它不会表现为“--force”,它仍然会失败。 (2认同)

G. *_*ies 5

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

git push --force
Run Code Online (Sandbox Code Playgroud)

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

git push --force-with-lease
Run Code Online (Sandbox Code Playgroud)

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

  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
Run Code Online (Sandbox Code Playgroud)

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

  • 我认为这个答案比评级较高的答案更容易理解并且更有用。谢谢你解释得这么好! (8认同)
  • 如果检查是在客户端进行的,是否存在竞争条件的可能性?即其他人在检查之后但在强制推送之前推送更改? (2认同)