即使对于拒绝的推送,GIT也会使用receive.denyCurrentBranch = updateInst更新工作树(receive.denyNonFastForwards = true)

时间:2018-10-18 15:02:22

标签: git

我将此问题/错误发布到GIT官方频道,但未得到任何回应。希望有人可以帮助我。

receive.denyCurrentBranch 设置为 updateInstead 时,以下行为对我来说似乎是不正确的 receive.denyNonFastForwards 设置为 true 。以下是步骤 重现场景。

步骤1-设置远程存储库(远程主机):

git config --global receive.denyCurrentBranch updateInstead
git config --global receive.denyNonFastForwards true
mkdir /tmp/hello
cd /tmp/hello
git init
echo hello > hello.txt
git add . && git commit -m "hello.txt"

步骤2-创建2个克隆(本地主机):

git clone ssh://REMOTEIP/tmp/hello /tmp/hello1
git clone ssh://REMOTEIP/tmp/hello /tmp/hello2

第3步-从克隆1推送提交

cd /tmp/hello1
echo hello1 > hello1.txt
git add . && git commit -m "hello1.txt"
git push

这时服务器工作树包含预期的hello1.txt

步骤4:尝试从克隆2强制推送提交

cd /tmp/hello2
echo hello2 > hello2.txt
git add . && git commit -m "hello2.txt"
git push

Remote拒绝,并显示一条消息,其中Remote包含我在本地没有有效的工作。现在我强行推动。

git push --force

远程再次拒绝并出现错误:拒绝非快进 裁判/负责人/大师(你应该先拉)

在这一点上,由于推送被拒绝,我希望服务器 工作树中不包含任何拒绝的更改。但是服务器 工作树已更新,可以删除hello1.txt并创建hello2.txt。 推送被拒绝,但不是真的。

当更新挂钩时,我也注意到了相同的行为(不正确) 拒绝服务器上的更改(但不拒绝预接收挂钩)。

2 个答案:

答案 0 :(得分:4)

问题在于这两种配置存在冲突(尽管我同意原则上不应是):

  

receive.denyCurrentBranch设置为updateInstead

在这种情况下,Git在接收期间会注意到目标是当前分支,因此Git会检查提交。

  

receive.denyNonFastForwards设置为true

这是单独发生的:名称的更改被拒绝。提交已被执行,并且存储库签出发生,并且 now name 的更改被拒绝。

  

当更新挂钩拒绝服务器上的更改(但不是预先接收挂钩)时,我也注意到了相同的行为(不正确)。

这是相同的问题:pre-receive挂钩在任何单个引用更新之前运行一次,并且可以拒绝整个推送。然后,如果预接收钩子清除了要继续的操作,则更新钩子可以拒绝任何单独的引用名更新。但是,updateInstead与接受或拒绝分支名称更新是分开发生的。

对于Git,最好在内部审查工作表更改,直到之后审核参考更新。这将需要对Git的内部进行一些重做。如果这不是Git中的彻底错误,那至少是相当令人惊讶的。实际上,所有这些代码仍然需要一些工作,因为如果您使用git worktree add,Git将无法将添加的工作树的HEAD视为当前分支。考虑到所有这些警告,我建议仅使用裸存储库作为推送目标,并使用后接收挂钩直接在其他存储库或工作树中进行更新。


放在一边(这是一条评论,但是太短了,无法很好地表达出来):

git config --global receive.denyCurrentBranch updateInstead
git config --global receive.denyNonFastForwards true

尽管这与您观察到的特定行为无关,但这绝对是错误的做法。运行git config --global会为您个人设置配置项目。也就是说,它们进入/home/rajesh(或您的主目录配置所在的位置)。但是receive.*的设置应为每个存储库

由于您自己使用ssh进行推送,因此这些配置参数确实生效-但是,如果您曾经通过其他方法进行推送,则它们可能不会生效。使用git config而不使用--global进行的每个存储库设置仍将生效。

答案 1 :(得分:0)

  

我希望服务器的工作树中不包含任何拒绝的更改。但是服务器工作树已更新,可以删除hello1.txt并创建hello2.txt。
  推送被拒绝,但不是真的。

从Git 2.20开始(2018年第四季度),该推送将确实被拒绝。

在此之前,receive.denyCurrentBranch=updateInstead代码路径也会被踢入,即使在推送由于其他原因而被拒绝的情况下,例如它没有快进或更新挂钩也已将其纠正。

请参见commit b072a25Junio C Hamano (gitster)(2018年10月19日)。
(由Junio C Hamano -- gitster --commit 4c7f544中合并,2018年10月30日)

  

receivedenyCurrentBranch=updateinstead不应盲目更新

     

receive.denyCurrentBranch=updateInstead的处理已添加到   一个处理该变量其他值的switch语句,但是   其他所有案件仅检查条件以拒绝   尝试推送,或让同一功能中的后续逻辑仍然   进行干预,以使推送不会快速前进(即   在有问题的switch语句后检查)。

     

但是updateInstead的处理错误地立即生效,   而没有给予其他支票干预的机会。

     

而不是调用会引起副作用的update_worktree()   立即,请注意我们需要致电   稍后再运行,然后先给其他支票一个拒绝的机会   请求。
  在update-hook有机会拒绝推送之后(发生在一系列检查的最后一步),请在我们较早发现需要这样做时致电update_worktree()

在您的情况下,考虑到您的推送被拒绝,按预期,您的工作树将包含任何被拒绝的更改。