我想在我们的git服务器中设置一个预接收挂钩来检查配置文件并丢弃推送它是否无效(我想根据分支名称检查某些令牌的存在)。但是我已经看过,先前的钩子只收到一个(old-rev,new-rev,refname)列表,而我发现检查文件内容的唯一方法就是区分这些引用,这不是很容易。
有一种简单的方法吗? 使用precommit hook会更容易,但我想在服务器中设置最后一个屏障。
答案 0 :(得分:5)
在将新对象(提交,带注释的标记对象,树和blob)加载到存储库中之后但在引用(分支名称,标记名称等)之前已经调用了预接收或更新挂钩改变。
这是为什么预接收挂钩获取( old
, new
,< em> ref
)三元组:现有的repo具有对象,现有的ref(如果有的话)指向对象(通常是commit,有时是标记),其SHA-1是 {{1 }} 的。 Git建议将其更改为指向SHA-1为 old
的对象(或创建它或删除它,如果这两者中只有一个是全零“null SHA- 1" )。
我发现检查文件内容的唯一方法是区分这些引用
这是一种方式,但是您可以使用整套git命令来提取所有内容。例如,您可以在某处创建一个新的空目录(new
)并运行mkdir path
以获得该路径的完整树。 (如果树很大,这可能需要一些时间。当然,你运行的任何测试都需要更多的时间。)
您必须确定要检查的内容。这与您希望的一样复杂,但对于分支名称({em> git --work-tree=path checkout sha1
形式为ref
,其中 refs/heads/name
是任何分支名称,即可能包含更多斜杠),请考虑ref更新可能会执行以下一项或多项操作(某些组合显然是不可能的):
例如,如果我有一个裸仓库name
的克隆,我会这样做:
origin
然后更新将删除三个提交并再添加两个。如果您签出了 git fetch origin # get up-to-date with origin
git checkout -b branch origin/branch # make tracking branch for origin/branch
git reset --hard HEAD~3 # back up 3 commits
echo more stuff >> existing_file # modify something
git commit -a -m 'add new text' # commit the change
git revert --no-edit HEAD # add another commit that undoes change
git push -f origin branch # and push
SHA-1(再次使用 new
, {{1} } , old
三重符号)看起来与我要求推送的版本完全一样。如果有一些树必须通过的测试,可能是new
的版本实际上通过了那些测试,所以这个版本也是如此。但是,我提交的向ref
添加一行的内容可能不通过了测试,您可能不喜欢我删除了三次提交的事实。
所以,再次,由您来决定要检查的内容,并编写代码来实现这一目标。检查强制推送是否正在删除提交;允许或禁止此。检查是否正在创建新的分支名称;允许或禁止。检查是否删除了分支名称;允许或禁止。如果要添加提交,请检查每个中间提交的树,或仅检查最终树;允许或禁止。添加的提交是否涉及合并?标签是否被添加,删除或更改?等等。
只是为了好玩,不久之前我写了一个pre-receive shell script(在POSIX风格的shell中)执行了很多这些(它没有检查任何提交的内容)。我做了一些非常轻的测试,它似乎工作。它可以作为更彻底检查的起点。
但是,如果您正在进行认真检查,则可能需要考虑使用gitolite。