我在试着理解
git push --force
以及
git push --force-with-lease
我的猜测是后者只会在远程分支有本地分支没有的提交时才推送到远程分支 *?
flseospp1#
force用本地分支覆盖远程分支。--force-with-lease是一个更安全的选项,如果有更多的提交被添加到远程分支(由另一个团队成员或同事或您所拥有的),它不会覆盖远程分支上的任何工作,它确保您不会通过强制推送来覆盖其他人的工作。我认为你对这个命令的总体想法是正确的。如果remote分支和你本地机器上的remote分支有相同的值--你将覆盖remote。如果它没有相同的值--它表明当你在你的代码上工作时其他人对remote分支做了改变,因此不会覆盖任何代码。显然,如果在remote中有额外的提交,那么这些值将不会被覆盖。It’不会一样的。我只是把--force-with-lease作为一个选项,当我想确保我不覆盖任何队友的代码时使用。我公司的许多团队使用--force-with-lease作为故障安全的默认选项。它在大多数情况下是不必要的,但如果你碰巧覆盖了另一个人贡献给远程的东西,它会让你省去很多麻烦。我相信你看了文件,但可能有一些更罗嗦的解释包含在这里:https://git-scm.com/docs/git-push
force
--force-with-lease
fae0ux8s2#
从可靠和/或官方来源寻找答案。torek在注解和his other answer中提到的"比较和交换"在sources of Git itself中得到了进一步的说明。后者只在远程分支没有本地分支没有的提交时才推送到远程分支?该特性是在this commit中引入的(2013年12月,Git v1.8.5-rc0)--force-with-lease将通过要求它们的当前值与某个合理的默认值相同来保护将要被更新的所有远程引用,除非另外指定;现在,"某个合理的默认值"被暂时定义为"我们为正在更新的远程节点的ref所拥有的远程跟踪分支的值",如果我们没有这样的远程跟踪分支,这将是一个错误。所以"租赁"的意思是:"force-with-lease":您假设在获取以决定重定基历史应该是什么时租用了ref,并且只有在租约没有被打破时才能回推。资料中仍然提到"cas":
force-with-lease
cas
您假设在获取以决定重定基历史应该是什么时租用了ref,并且只有在租约没有被打破时才能回推。因此:"git push --force-with-lease与--force"正如我在"push --force-with-lease by default"中提到的,正如Git 2.13(Q2 2017)提到的,如果后台进程(就像您在带有Git插件的IDE中找到的进程)运行git fetch origin,则可以 * 忽略 * 选项--force-with-lease。在这种情况下,--force优先。正如Pavlus在注解中所添加的:它本身并没有被忽略,只是现在本地远程头端和远程头端具有相同引用,所以--force-with-lease将正确地工作--比较这两者,如果在fetch和push之间的时间间隔内,有人更新了remote,它将不会像--force那样工作,它仍然会失败。另一个区别:在Git 2.29(Q4 2020)之前,使用"--force-with-lease"选项推送名称包含非ASCII字符的ref在智能HTTP协议上不起作用。它将与git push --force一起工作。参见brian m. carlson ( bk2204 )的commit cd85b44(2020年7月21日)。(由Junio C Hamano -- gitster --合并至commit c2796ac,2020年7月30日)
--force
push --force-with-lease
git fetch origin
bk2204
gitster
remote-curl
报告人:弗雷·比永签署人:布赖恩·卡尔森当我们调用远程传输帮助器并传递带有参数的选项时,如果需要,我们将参数作为C样式字符串引用。当我们传递一个非ASCII的refname时,cas选项就是这种情况,它实现了--force-with-lease命令行标志。但是,远程curl helper并不是设计来解析这样的参数的,这意味着如果我们尝试使用带有HTTP push和非ASCII refname的--force-with-lease,我们会得到如下错误:
curl
error: cannot parse expected object name '0000000000000000000000000000000000000000"'
请注意,get_oid提醒我们的双引号在十六进制对象ID中无效。即使我们能够解析它,我们也会向服务器发送错误的数据:我们会发送一个转义的ref,这将不会按照用户想要的方式运行,并且可能会意外地导致更新或删除我们不希望的ref。因为我们需要在这里使用带引号的C样式字符串,所以只需要检查第一个参数是否是双引号,如果是,就取消引号。注意,如果refname包含双引号,那么我们已经用双引号引起来了,所以没有歧义。我们仅在智能协议中测试这种情况,因为基于DAV的协议无法处理这种能力。我们使用UTF-8是因为它在我们的测试中更好,并且对Windows更友好,但是代码应该对所有非ASCII引用都有效。既然这样,既然选项的名称已经很好地确定,并且不会更改,那么让我们内联它,而不是使用#define常量。Git 2.30(2021年第一季度)增加了git push --force-if-includes当基于远程引用的本地分支已被回退并将被强制推送到远程上时,"--force-if-includes"运行检查,以确保可能已发生的对远程跟踪引用的任何更新(通过从另一个资料库推送)在上次更新到本地分支的时间之间(例如,通过"git pull")并且恰好在推送时间之前,在允许强制更新之前已经被本地集成。
get_oid
git push --force-if-includes
--force-if-includes
git pull
inn6fuwd3#
git push --force是破坏性的,因为它会无条件地覆盖远程仓库中本地的所有内容。强烈建议不要使用git的push --force,因为它会破坏其他已经推送到共享仓库中的提交。强制推送最常见的原因之一是当我们被迫对分支进行重定基时。例如,我们有一个项目,它有一个特性分支,Alice和Bob都要处理。他们克隆这个仓库并开始工作。Alice最初完成了特性的她的部分,并将其推送到主仓库。这一切都很好。Bob也完成了他的工作,但在推送到主仓库之前,他注意到一些更改已经合并到主仓库中。想要保持一个干净的树,他对master分支执行了一个rebase。当然,当他去推送这个rebase分支时,它会被拒绝。然而,他没有意识到Alice已经推送了她的工作,他执行了一个push-force。不幸的是,这将擦除中央存储库中Alice的所有更改记录。--force-with-lease所做的是拒绝更新一个分支,除非它是我们所期望的状态;也就是说,没有人更新上游分支,实际上,这是通过检查上游引用是否是我们所期望的来实现的,因为引用是散列,并且隐式地将父级链编码到它们的值中。这里有一个关于git push --force和git push --force-with-lease的好帖子:–force considered harmful; understanding git’s –force-with-lease
push --force
c3frrgcw4#
假设服务器上的任何pre-receive钩子都接受了push,这将总是成功的:
而这将在继续之前运行特定的客户端检查:
您可以自己手工运行具体的检查,“查租”算法如下:1.弄清楚你现在的分支。1.运行git for-each-ref refs/remotes,记下git客户端认为对应于当前分支上游状态的commit-id。例如,如果您在分支“foo”上,请注意与“refs/remotes/origin/foo”关联的commit-id。1.立即确定上游git服务器上远程分支的实际commit-id。1.只有在步骤2和步骤3中提取的commit-id一致的情况下,才允许“git push”继续,换句话说,只有在本地git克隆的上游概念与实际上游一致的情况下,才允许“git push”继续。这里有一个悲伤的暗示:由于git fetch将“refs/remotes/origin/*”下的所有refs更新为它们的最新版本,因此该命令组合基本上与git push --force相同:
git for-each-ref refs/remotes
git fetch
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 pull --rebase
qc6wkl3g5#
Force-with-lease不一定安全,它只是像Sylvie说的那样工作。
Force-with-lease
**注意:**在git中,分支只是一个提交上的指针,而提交指向零个或多个父提交。即使你使用git硬重置和强制推送,或者使用强制推送和租约来完全改变分支,这也不一定是一个大问题。
你可以使用本地git reflog来查看本地分支提示(HEAD当时在哪里?)是如何改变的,然后重置并再次推送分支。这样你只会丢失远程分支上的新提交,但即使是这些提交也可能被团队成员恢复。
git reflog
5条答案
按热度按时间flseospp1#
force
用本地分支覆盖远程分支。--force-with-lease
是一个更安全的选项,如果有更多的提交被添加到远程分支(由另一个团队成员或同事或您所拥有的),它不会覆盖远程分支上的任何工作,它确保您不会通过强制推送来覆盖其他人的工作。我认为你对这个命令的总体想法是正确的。如果remote分支和你本地机器上的remote分支有相同的值--你将覆盖remote。如果它没有相同的值--它表明当你在你的代码上工作时其他人对remote分支做了改变,因此不会覆盖任何代码。显然,如果在remote中有额外的提交,那么这些值将不会被覆盖。It’不会一样的。
我只是把
--force-with-lease
作为一个选项,当我想确保我不覆盖任何队友的代码时使用。我公司的许多团队使用--force-with-lease
作为故障安全的默认选项。它在大多数情况下是不必要的,但如果你碰巧覆盖了另一个人贡献给远程的东西,它会让你省去很多麻烦。我相信你看了文件,但可能有一些更罗嗦的解释包含在这里:
https://git-scm.com/docs/git-push
fae0ux8s2#
从可靠和/或官方来源寻找答案。
torek在注解和his other answer中提到的"比较和交换"在sources of Git itself中得到了进一步的说明。
后者只在远程分支没有本地分支没有的提交时才推送到远程分支?
该特性是在this commit中引入的(2013年12月,Git v1.8.5-rc0)
--force-with-lease
将通过要求它们的当前值与某个合理的默认值相同来保护将要被更新的所有远程引用,除非另外指定;现在,"某个合理的默认值"被暂时定义为"我们为正在更新的远程节点的ref所拥有的远程跟踪分支的值",如果我们没有这样的远程跟踪分支,这将是一个错误。
所以"租赁"的意思是:
"
force-with-lease
":您假设在获取以决定重定基历史应该是什么时租用了ref,并且只有在租约没有被打破时才能回推。资料中仍然提到"cas":
cas
"("比较和交换"的意思),这个名字没有人喜欢,因为它太技术化了。您假设在获取以决定重定基历史应该是什么时租用了ref,并且只有在租约没有被打破时才能回推。
因此:"
git push --force-with-lease
与--force
"正如我在"
push --force-with-lease
by default"中提到的,正如Git 2.13(Q2 2017)提到的,如果后台进程(就像您在带有Git插件的IDE中找到的进程)运行git fetch origin
,则可以 * 忽略 * 选项--force-with-lease
。在这种情况下,
--force
优先。正如Pavlus在注解中所添加的:
它本身并没有被忽略,只是现在本地远程头端和远程头端具有相同引用,所以
--force-with-lease
将正确地工作--比较这两者,如果在fetch和push之间的时间间隔内,有人更新了remote,它将不会像--force
那样工作,它仍然会失败。另一个区别:在Git 2.29(Q4 2020)之前,使用"
--force-with-lease
"选项推送名称包含非ASCII字符的ref在智能HTTP协议上不起作用。它将与
git push --force
一起工作。参见brian m. carlson (
bk2204
)的commit cd85b44(2020年7月21日)。(由Junio C Hamano --
gitster
--合并至commit c2796ac,2020年7月30日)remote-curl
:使--force-with-lease
使用非ASCII引用名称报告人:弗雷·比永
签署人:布赖恩·卡尔森
当我们调用远程传输帮助器并传递带有参数的选项时,如果需要,我们将参数作为C样式字符串引用。
当我们传递一个非ASCII的refname时,cas选项就是这种情况,它实现了
--force-with-lease
命令行标志。但是,远程
curl
helper并不是设计来解析这样的参数的,这意味着如果我们尝试使用带有HTTP push和非ASCII refname的--force-with-lease
,我们会得到如下错误:请注意,
get_oid
提醒我们的双引号在十六进制对象ID中无效。即使我们能够解析它,我们也会向服务器发送错误的数据:我们会发送一个转义的ref,这将不会按照用户想要的方式运行,并且可能会意外地导致更新或删除我们不希望的ref。
因为我们需要在这里使用带引号的C样式字符串,所以只需要检查第一个参数是否是双引号,如果是,就取消引号。
注意,如果refname包含双引号,那么我们已经用双引号引起来了,所以没有歧义。
我们仅在智能协议中测试这种情况,因为基于DAV的协议无法处理这种能力。
我们使用UTF-8是因为它在我们的测试中更好,并且对Windows更友好,但是代码应该对所有非ASCII引用都有效。
既然这样,既然选项的名称已经很好地确定,并且不会更改,那么让我们内联它,而不是使用#define常量。
Git 2.30(2021年第一季度)增加了
git push --force-if-includes
当基于远程引用的本地分支已被回退并将被强制推送到远程上时,"
--force-if-includes
"运行检查,以确保可能已发生的对远程跟踪引用的任何更新(通过从另一个资料库推送)在上次更新到本地分支的时间之间(例如,通过"git pull
")并且恰好在推送时间之前,在允许强制更新之前已经被本地集成。inn6fuwd3#
git push --force
是破坏性的,因为它会无条件地覆盖远程仓库中本地的所有内容。强烈建议不要使用git的push --force
,因为它会破坏其他已经推送到共享仓库中的提交。强制推送最常见的原因之一是当我们被迫对分支进行重定基时。例如,我们有一个项目,它有一个特性分支,Alice和Bob都要处理。他们克隆这个仓库并开始工作。Alice最初完成了特性的她的部分,并将其推送到主仓库。这一切都很好。Bob也完成了他的工作,但在推送到主仓库之前,他注意到一些更改已经合并到主仓库中。想要保持一个干净的树,他对master分支执行了一个rebase。当然,当他去推送这个rebase分支时,它会被拒绝。然而,他没有意识到Alice已经推送了她的工作,他执行了一个push-force。不幸的是,这将擦除中央存储库中Alice的所有更改记录。
--force-with-lease
所做的是拒绝更新一个分支,除非它是我们所期望的状态;也就是说,没有人更新上游分支,实际上,这是通过检查上游引用是否是我们所期望的来实现的,因为引用是散列,并且隐式地将父级链编码到它们的值中。这里有一个关于
git push --force
和git push --force-with-lease
的好帖子:–force considered harmful; understanding git’s –force-with-leasec3frrgcw4#
假设服务器上的任何pre-receive钩子都接受了push,这将总是成功的:
而这将在继续之前运行特定的客户端检查:
您可以自己手工运行具体的检查,“查租”算法如下:
1.弄清楚你现在的分支。
1.运行
git for-each-ref refs/remotes
,记下git客户端认为对应于当前分支上游状态的commit-id。例如,如果您在分支“foo”上,请注意与“refs/remotes/origin/foo”关联的commit-id。
1.立即确定上游git服务器上远程分支的实际commit-id。
1.只有在步骤2和步骤3中提取的commit-id一致的情况下,才允许“git push”继续,换句话说,只有在本地git克隆的上游概念与实际上游一致的情况下,才允许“git push”继续。
这里有一个悲伤的暗示:由于
git fetch
将“refs/remotes/origin/*”下的所有refs更新为它们的最新版本,因此该命令组合基本上与git push --force
相同:为了解决
git push --force-with-lease
的这个固有缺陷,我尽量不运行git fetch
,而是在需要与上游同步时总是运行git pull --rebase
,因为git pull
只更新refs/remotes下的单个ref,使--force-with-lease
的“租约”保持有用。qc6wkl3g5#
Force-with-lease
不一定安全,它只是像Sylvie说的那样工作。**注意:**在git中,分支只是一个提交上的指针,而提交指向零个或多个父提交。即使你使用git硬重置和强制推送,或者使用强制推送和租约来完全改变分支,这也不一定是一个大问题。
你可以使用本地
git reflog
来查看本地分支提示(HEAD当时在哪里?)是如何改变的,然后重置并再次推送分支。这样你只会丢失远程分支上的新提交,但即使是这些提交也可能被团队成员恢复。