Git 如何检测强制更新
在远程上更改分支历史记录时,通常会Git 如何检测强制更新,git,Git,在远程上更改分支历史记录时,通常会 o git@git.server.com:XXXXX/Project.git + efe2e8b...cda0ee7 HEAD -> Ant_Config_processing (forced update) 有没有办法使用脚本获取此(强制更新)状态 其思想是编写一个别名来检测它并提示用户进行操作。一种方法是使用git reflog,它会记录分支的更改 使用reflog,您可以在拉/取之前获得分支指向的位置(如果它是脚本化的,我将使用取,因为它不会自
o git@git.server.com:XXXXX/Project.git
+ efe2e8b...cda0ee7 HEAD -> Ant_Config_processing (forced update)
有没有办法使用脚本获取此(强制更新)状态
其思想是编写一个别名来检测它并提示用户进行操作。一种方法是使用
git reflog
,它会记录分支的更改
使用reflog,您可以在拉/取之前获得分支指向的位置(如果它是脚本化的,我将使用取,因为它不会自动合并),并检查是否可以从新远程分支的“提示”访问该提交
使用bash,您可以尝试以下操作:
$ git rev-list remotename/branchname | grep $(git rev-parse remotename/branchname@{1})
$ echo $?
1
如果它返回一个散列(或退出状态0),则表示它在分支历史记录中找到了我们以前的分支提示,因此它是一个快进合并。如果不返回任何内容(或退出状态1),则强制更新
$ git reflog remotename/branchname
dc2afab refs/remotes/remotename/branchname@{0}: fetch rewrite: forced-update
4603c2c refs/remotes/remotename/branchname@{1}: fetch rewrite: forced-update
您可以检查git reflog remotename/branchname
输出,查看branchname是否得到强制更新
$ git reflog remotename/branchname
dc2afab refs/remotes/remotename/branchname@{0}: fetch rewrite: forced-update
4603c2c refs/remotes/remotename/branchname@{1}: fetch rewrite: forced-update
我有一个类似的问题,我发现了 我想在远程(裸)存储库的钩子脚本中检测强制更新,所以我的答案可能不适合原始问题,但我希望我的答案对未来的访问者有用
如何在Git hooks脚本中检测强制更新或不强制更新 这是一个git预接收钩子脚本示例,用于学习如何检测强制更新
$ git reflog remotename/branchname
dc2afab refs/remotes/remotename/branchname@{0}: fetch rewrite: forced-update
4603c2c refs/remotes/remotename/branchname@{1}: fetch rewrite: forced-update
结论
如何测试
逐步介绍
首先,我描述了的语法
在本例中,我们假设在Git工作存储库中有这样的直接历史记录
1 --- 2 --- O --- X --- 3 --- 4 --- N
git版本列表的一般用法如下所示
$ git rev-list N
此命令将显示从commit N可访问的所有提交(注意:git rev list
按逆时间顺序显示提交)
git rev list
接受多个参数
$ git rev-list N O
此命令将显示与git rev list N相同的输出,因为commit O是commit N的祖先
然后,git rev list
允许您从输出中排除提交
$ git rev-list N ^O
^O表示要排除可从O访问的提交,因此此命令将显示N、4、3、X(注意:O被排除)
由于我们了解了git rev list
,我将描述一个发生强制更新的案例
在本例中,我们假设在Git工作存储库中有这样复杂的历史
* --- B --- * --- O ($oldrev)
\
* --- X --- * --- N ($newrev)
git rev list
输出检测强制推送
git rev list oldrev^newrev
显示可从oldrev访问但不能从newrev访问的提交。这表明提交只存在于旧树中。
如果此命令显示任何提交,则旧树将替换为新树,因此发生强制更新。这就是我们想要的
如果此命令不显示任何提交,则新树通常会更新,因此不会发生强制更新。很简单
另见
git merge base
命令,它为两次提交查找最近的公共祖先
对于快进更新,oldrev
和newrev
的共同祖先必须指向oldrev
。要放入预接收挂钩以阻止非快进的示例代码:
mergebase=`git merge-base $oldrev $newrev`
if [ "$oldrev" != "$mergebase" ]; then
echo "Non fast-forward update not allowed for $refname, from ${oldrev:0:16} to ${newrev:0:16} merge base ${mergebase:0:16}"
exit 1
fi
man-githooks
提到了update
,它可以用来阻止强制更新(或类似的事情)。你可以使用receive.denynonfastforts
配置选项来阻止强制更新…但我不确定是否可以从git-hook检测到这样的更新。谢谢,但我只需要检测,该操作可能与blocking.Nov不同。2018年:在GitHub上,现在更容易了:@larsks这对服务器端来说是一个很好的提示,但问题是关于客户端。这是个好主意,让我在不同的场景中尝试一下,应该可以工作git reflog origin/master | head-1 | grep forced update
Hey@kyanny,也许你能添加最后1-2行?(我不确定如何检查git rev list oldrev^newrev
脚本中是否存在空白。)