Git push——force-with-lease vs.——force

我在试着理解两者的区别

git push --force

而且

git push --force-with-lease

我的猜测是后者只推到远程如果远程具有本地分支没有的提交?

237698 次浏览

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

--force-with-lease是一个更安全的选项,它不会覆盖远程分支上的任何工作,如果更多的提交被添加到远程分支(由另一个团队成员或同事或其他什么人添加)。它确保你不会通过强行推动而覆盖别人的工作。

我认为你关于命令的总体想法是正确的。如果远程分支与本地机器上的远程分支具有相同的值-您将覆盖remote。如果它没有相同的值—它表明在您处理代码时其他人对远程分支所做的更改,因此不会覆盖任何代码。显然,如果远程中有额外的提交,那么这些值就不会相同。

我只是认为--force-with-lease作为我想要确保我不覆盖任何队友代码时使用的选项。我公司的许多团队使用--force-with-lease作为故障保险的默认选项。这在大多数情况下是不必要的,但如果你碰巧覆盖了另一个人贡献给远程的东西,它会为你省去很多麻烦。

我相信你看了文件,但这里可能有一些更啰嗦的解释:

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

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

“比较和交换”;torek的评论他的另一个回答中提到的是由Git本身的来源进一步说明的。

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

该特性在这个承诺(2013年12月,Git v1.8.5-rc0)中引入

--force-with-lease将保护所有将被更新的远程引用,要求它们的当前值与一些合理的默认值相同,除非另有指定;

目前,“一些合理的违约”;暂定定义为"用于更新远程的引用的远程跟踪分支的值",如果我们没有这样的远程跟踪分支,这是一个错误。

所以“lease"意思是:

:您假设在获取时对ref进行了租约以决定重基历史应该是什么,并且只有在租约没有被打破时才能推回。

资料来源仍然提到“cas"”:

  • 这个选项最初被称为“cas"(代表“比较和交换”),没有人喜欢这个名字,因为它太专业了。
  • 第二次尝试称之为“lockref"(因为它在概念上就像开了锁后推)但“锁”这个词;被讨厌是因为这意味着它可能会拒绝其他人的推动,而这并不是这个选项的工作方式。
  • 这一轮称之为“强制租赁”。
    您假设在获取时对ref进行了租用,以决定应该是什么重基历史,并且只有在 租约未被打破。

所以:git push --force-with-lease vs # eyz1;

正如我在&;# eyz3 &;中提到的,正如Git 2.13 (Q2 2017)提到的,如果后台进程(就像你在带有Git插件的IDE中发现的进程)运行git fetch origin,选项--force-with-lease可以是< < em >忽略/ em >
在这种情况下,--force优先

Pavlus添加在评论中:

它本身并没有被忽略,只是现在你对本地远程头和远程头有相同的引用,所以--force-with-lease将正确地运行——比较这两个,如果在获取和推送之间的时间间隔内,有人更新了远程,它不会像--force那样运行,它仍然会失败。


另一个不同之处是:在Git 2.29 (Q4 2020)之前,push名称包含“# eyz0”非ascii字符的ref;选项不能在智能HTTP协议上工作。
它将与git push --force工作。

参见提交cd85b44(2020年7月21日)by 布莱恩·m·卡尔森(bk2204)
(由滨野朱尼奥——gitster——提交c2796ac中合并,2020年7月30日)

remote-curl:使--force-with-lease适用于非ascii引用名称

< p > # EYZ0
署名:brian m. carlson

当调用远程传输助手并传递带有参数的选项时,必要时将参数作为c风格字符串引用。
这就是cas选项的情况,当我们传递一个非ascii的refname时,它实现了--force-with-lease命令行标志

然而,远程的curl helper并不是设计来解析这样的参数的,这意味着如果我们试图使用--force-with-lease与HTTP推送和非ascii refname一起使用,我们会得到这样的错误:

error: cannot parse expected object name '0000000000000000000000000000000000000000"'

注意双引号,get_oid已经提醒我们,在十六进制对象ID中是无效的。

即使我们能够解析它,我们也会向服务器发送错误的数据:我们会发送一个转义的ref,它的行为不会像用户想要的那样,可能会意外地导致更新或删除我们不想要的ref。

由于我们需要在这里使用带引号的c风格字符串,因此只需检查第一个参数是否为双引号,如果是,则取消其引号。
注意,如果refname包含双引号,那么我们已经用双引号对其进行了标记,因此不存在歧义 我们仅在智能协议中测试这种情况,因为基于dave的协议无法处理这种功能。
我们使用UTF-8,因为这在我们的测试中更好,对Windows更友好,但代码应该适用于所有非ascii引用

当我们这样做的时候,因为选项的名称现在已经很好地建立起来,并且不会改变,让我们内联它,而不是使用#define常量。


Git 2.30 (Q1 2021)添加了git push --force-if-includes

当基于远程引用的本地分支被重绕并将被强制推到远程上时,&;--force-if-includes"运行一个检查,确保在最后一次更新到本地分支之间(例如,通过"git pull")和在推送之前对远程跟踪引用可能发生的任何更新(从另一个存储库推送),在允许强制更新之前已经在本地集成。

假设服务器上的任何pre-receive钩子都接受推送,这将总是成功:

git push --force

而这在继续之前会运行特定的客户端检查:

git push --force-with-lease

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

  1. 计算出当前的分支。

  2. # EYZ0运行。注意git客户端认为对应于当前分支上游状态的commit-id。

例如,如果你在分支“foo”上,请注意与“refs/remotes/origin/foo”相关的commit-id。

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

  2. 只有在从第2步和第3步提取的commit-id同意的情况下,才允许“git推送”继续进行。换句话说,只有当本地git克隆的上游概念与实际的上游一致时,才继续执行。

这里有一个悲伤的暗示:因为git fetch将“refs/remotes/origin/*”下的所有引用更新到最新版本,这个命令组合本质上与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只在refs/remotes下更新一个ref,保持--force-with-lease的“租约”有用。

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

例如< p >。我们有一个带有特征分支的项目,Alice和Bob都将参与其中。它们都克隆了这个存储库并开始工作。 Alice最初完成了她的部分功能,并将其推到主存储库。这一切都很好。Bob也完成了他的工作,但在把它推上去之前,他注意到一些更改已经合并到master中。为了保持树的干净,他对主分支执行了一个rebase。当然,当他去推动这个重基分支时,它将被拒绝。然而,他没有意识到爱丽丝已经推了她的作品,他执行了一个推力。不幸的是,这将删除Alice在中央存储库中的所有更改记录

--force-with-lease所做的是拒绝更新分支,除非它是我们所期望的状态;也就是说,没有人更新上游的分支。在实践中,这是通过检查上游的ref是否是我们所期望的,因为ref是哈希值,并隐式地将父链编码到它们的值中。

这里有一个关于git push --forcegit push --force-with-lease的好帖子:-被认为有害的力量;理解git的-force-with-lease

强制租赁并不一定安全。就像西尔维说的那样。注意:在git中,分支只是一个提交上的指针。并且提交指向零个或多个父提交。即使你通过硬git重置和强制推送完全改变了分支,或者在不想要的情况下使用- force-with-lease推送,这也不一定是一个大问题。你可以使用你的本地git reflog来查看你的本地tip在分支上的情况(当时HEAD在哪里?)已更改和重置,并再次推动分支。那么您只会丢失远程分支上的新提交,但即使它们也可能被团队成员恢复。