在寻找 git hook 示例时,我遇到了以下帖子:https : //github.com/Movidone/git-hooks/blob/master/pre-receive,我想了解以下命令:
git rev-list $new_list --not --all
Run Code Online (Sandbox Code Playgroud)
从哪里获得 new_list:
NULL_SHA1="0000000000000000000000000000000000000000" # 40 0's
new_list=
any_deleted=false
while read oldsha newsha refname; do
case $oldsha,$newsha in
*,$NULL_SHA1) # it's a delete
any_deleted=true;;
$NULL_SHA1,*) # it's a create
new_list="$new_list $newsha";;
*,*) # it's an update
new_list="$new_list $newsha";;
esac
done
Run Code Online (Sandbox Code Playgroud)
我认为 rev-list 以相反的时间顺序显示提交。
但是,有人可以分享更多关于什么-not和-all选项的含义的见解吗?
根据文档:
--not
Reverses the meaning of the ^ prefix (or lack thereof) for all following revision specifiers, up to the next --not.
--all
Pretend as if all the refs in refs/ are listed on the command line as <commit>.
Run Code Online (Sandbox Code Playgroud)
我无法完全理解这些选项。
[更新] 在做了一些测试提交之后,我想如果我不使用--not和--all选项,那么git rev-list列出分支上的所有提交,而不是我打算推送的那个。
但是,想了解为什么在--all传递选项时不在终端上打印 sha 值?
该git rev-list命令是Git 中一个非常复杂、非常核心的命令,因为它的作用是遍历图形。这里的词图既指提交图本身,在某些情况下,也指下一级(可从提交访问的Git 对象)。
我认为 rev-list 以相反的时间顺序显示提交。
不完全是,但接近:
rev-list更深入地包括树和 blob 对象,甚至标记对象。这适用于git fetch和git push(调用git pack-objects)和 之类的程序git pack-objects。我打算在这里完全忽略这种可能性,但我觉得我至少应该提到它。所以默认是按时间倒序列出一些提交。它既是重要的,有点棘手,指定究竟哪些零件图的,我们将有git rev-list散步:对一些在某些提交。
但是,有人可以分享更多关于什么
--not和--all选项的含义的见解吗?
正如VonC 所指出的,这里的效果是列出对接收存储库来说是新的提交。这取决于此git rev-list命令在pre-receive hook 中运行的事实。除了这个特定的钩子之外,它通常不会做任何有用的事情。因此,如您所见,在 Git 中,钩子的运行时环境通常至少有点特殊。(这不仅适用于 pre-receive 钩子:必须考虑每个钩子的激活上下文。)
--not --all该--all选项仅执行您从文档中引用的内容:
假装所有的 refs
refs/都列在命令行上......
所以这相当于 a git for-each-ref refs: 它遍历每个引用。这包括分支名称(master或main,develop,feature/tall,等等,所有这一切真的是refs/heads/),标签名称(v1.2这是真的refs/tags/v1.2),远程跟踪名称(origin/develop这是真的refs/remotes/origin/develop),更换裁判(中refs/replace/),藏匿(refs/stash)如果您使用的是 Gerrit,则为二分引用、Gerrit 引用,等等。请注意,它不会遍历 reflog 条目。
该--not前缀是一个简单的布尔运算。在 gitrevisions 语法中——请参阅gitrevisions 文档——我们可以写这样的东西develop,意思是我告诉你从头开始,develop向后工作并包括这些提交,但也可以写这样的东西^develop,意思是我告诉你从头开始develop并向后工作并排除这些提交. 所以如果我写:
git rev-list feature1 feature2 ^main
Run Code Online (Sandbox Code Playgroud)
我要求 Git从名称feature1和标识的提交中遍历可到达的提交feature2,但从由 标识的提交中排除可到达的提交main。有关可达性和图形行走的一般概念的(更多)更多信息,请参阅Think Like (a) Git。
该--not运营商有效地翻转^每个参考:
git rev-list --not feature1 feature2 ^main
Run Code Online (Sandbox Code Playgroud)
可以说是简写,因为:
git rev-list ^feature1 ^feature2 main
Run Code Online (Sandbox Code Playgroud)
这将遍历可从 访问的提交列表main,但不包括可从feature1或访问的提交列表feature2。
--all如果您以正常的日常方式使用 Git,并且目前没有“分离的 HEAD”——分离的 HEAD 模式并不完全不正常,但它不是通常的工作方式——告诉它包含所有提交的--all选项,因为所有提交都可以从所有引用访问。1 因此有效地排除了所有提交。因此,添加到任何可能会列出某些提交的内容会产生抑制列表的效果。输出为空:我们为什么要打扰?git rev-list--not --all--not --allgit rev-list
如果你是在分离的头模式,并取得了一些新的提交,这个时候你是在交互式或冲突底垫的中部,例如,则可能发生git rev-list HEAD --not --all将列出那些提交是从可到达HEAD,但不是从任何分支的名称。例如,在该 rebase 中,这将只是您迄今为止复制的那些提交。
因此,“分离的 HEAD”模式将成为git rev-list --not --all从命令行有用的地方。但是对于您正在检查的情况——一个预接收钩子——我们并不是真正在命令行上。
当有人使用git push送提交给自己的Git,你的Git:
在实际执行任何请求的更新之前,您的 Git:
在第 2 步中添加到某个引用的所需对象从隔离区移动到 Git 的对象数据库。那些被拒绝的不是。
现在,考虑一个典型的git push. 我们得到一些新的提交和一个请求:创建一个新的分支名称feature/short,或者我们得到一些新的提交和一个请求:更新现有的分支名称develop以包括这些新的提交和旧的提交。
在上面的步骤 1 中,我们有一个新的哈希 ID。我们运行了一个循环来读取所有 ref 名称,以及它们当前和提议的新哈希 ID,并且该循环仅运行一次,因为只有一个名称被git push-ed。该哈希 ID 指的是一个或多个新提交,它们将被添加到此现有分支,或者是新分支独有的提示和其他提交。
我们现在想要检查这些提交,而不是从任何现有分支可访问的任何现有提交。为简单起见,而不是$new_list在我的其他答案中,让我们假设我们只有一个新的哈希 ID$new和分支名称的旧哈希 ID $old:如果分支是全新的,则为全零,或者如果它是一些有效的现有提交现有的分支名称。
如果新的提交在一个全新的分支上,那么:
git rev-list $new ^master ^develop ^feature/short ^feature/tall
Run Code Online (Sandbox Code Playgroud)
例如,如果我们知道唯一存在的分支是这四个分支(并且没有标签等需要担心),就会覆盖它们。但是,如果它们被添加到,比如说,develop呢?然后我们想排除当前在 上的提交develop。我们可以使用$old哈希 ID 来做到这一点:
git rev-list $new ^master ^$old ^feature/short ^feature/tall
Run Code Online (Sandbox Code Playgroud)
这将再次仅列出正在运行的人git push origin develop想要添加到我们的develop.
但是想想$old。这是一个哈希 ID。Git从哪里得到的?Git从name获得了这个哈希 ID 。这是一个预接收钩子;该名称尚未更新。所以名称是旧哈希 ID 的名称。这意味着: develop develop develop $old
git rev-list $new ^master ^develop ^feature/short ^feature/tall
Run Code Online (Sandbox Code Playgroud)
将还做的工作。
如果git rev-list $new后跟“而不是所有现有的”将完成这项工作,则:
git rev-list $new --not --branches
Run Code Online (Sandbox Code Playgroud)
会做的工作。这几乎就是我们这里的情况。
仅使用的错误--branches是它没有获得任何标签或其他参考。我们可以使用--not --branches --tags但--not --all更短,并且还获得所有其他参考。
所以这就是--not --all来自:它取决于预接收钩子的特殊情况。我们列出了新的哈希 ID,正如运行 a 的人所提议的那样git push,我们的 Git 以行列表的形式传递给我们。我们已经git rev-list遍历了提议更新的提交图,查看隔离区中的新提交,但排除了我们存储库中已有的所有提交。rev-list 命令生成这些哈希 ID,每行一个,然后我们在 shell 循环中读取这些 ID,并执行我们喜欢的任何操作来检查每个提交。
1隔离区在 Git 2.11 中是新的。在此之前,即使推送被拒绝,新对象也可以在存储库中保留一段时间。隔离区对于大多数人来说并不是什么大问题,但对于像 GitHub 这样的大型服务器来说,它可以为他们节省大量磁盘空间。
2请求可以是强制的,也可以是非强制的,如果是强制的,则可以是强制租用,也可以不是。此信息在 pre-receive 钩子中不可用(也不在更新钩子中),也就是说,嗯,我们只是说不太好,但是添加它存在兼容性问题。不过,大部分都是宜居的。钩子可以判断它是创建新引用还是删除现有引用请求,因为如果是这样,两个散列 ID 之一(旧的或新的)将是全零的“空散列”(这是保留的;不允许散列 ID为全零)。
| 归档时间: |
|
| 查看次数: |
1338 次 |
| 最近记录: |