我喜欢在我们的git服务器中设置一个预接收挂钩来检查配置文件,如果它无效则丢弃推送(我想根据分支名称检查某些令牌的存在).但是我已经看到了先前的钩子只是收到一个(old-rev,new-rev,refname)的列表,我发现检查文件内容的唯一方法是区分这些引用,这不是很容易.
是否有捷径可寻?使用预先挂钩它会更容易,但我想在服务器中有一个最后的障碍.
在将新对象(提交,带注释的标记对象,树和blob)加载到存储库中之后,但在引用(分支名称,标记名称等)已更改之前,将调用预接收或更新挂钩.
这就是为什么前收到钩得到的(列表old,new,ref)三元:现有回购有对象和现有REF(如果有的话)指向的对象(通常犯,有时标记),其SHA-1 old.Git建议将其更改为指向SHA-1所在的对象new(或创建它或删除它,如果这两者中只有一个是全零"null SHA-1").
我发现检查文件内容的唯一方法是区分这些引用
这是一种方式,但你有整套git命令来提取所有内容.例如,您可以在某处创建一个新的空目录()并运行以将完整的树放入该路径.(如果树很大,这可能需要一些时间.当然,你运行的任何测试都需要更多的时间.)mkdir pathgit --work-tree=path checkout sha1
您必须确定要检查的确切内容.这和你想要的一样复杂,但是对于分支名称(ref表单的一个,其中是任何分支名称,也就是说,可能包含更多斜杠),请考虑ref更新可能会执行以下一个或多个(某些组合显然是不可能的):refs/heads/namename
例如,如果我有一个裸仓库的克隆,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
Run Code Online (Sandbox Code Playgroud)
然后更新将删除三个提交并再添加两个.如果您签出newSHA-1(再次使用,三重符号)old,您将获得的树看起来与我要求推送的版本完全相同.如果有一些树必须通过的测试,可能是实际上通过那些测试的版本,所以这个版本也是如此.但是,我提交的添加一行的内容可能无法通过测试,您可能不喜欢我删除了三次提交的事实.newrefHEAD~3existing_file
因此,再次由您自己决定要检查的内容,并编写代码来实现这一目标.检查强制推送是否正在删除提交; 允许或禁止此.检查是否正在创建新的分支名称; 允许或禁止.检查是否删除了分支名称; 允许或禁止.如果要添加提交,请检查每个中间提交的树,或仅检查最终树; 允许或禁止.添加的提交是否涉及合并?标签是否被添加,删除或更改?等等.
只是为了好玩,前一段时间我写了一个pre-receive shell脚本(在POSIX风格的shell中),它执行了很多这些(它没有检查任何提交的内容).我做了一些非常轻的测试,它似乎工作.它可以作为更彻底检查的起点.
但是,如果您正在进行认真的检查,您可能需要考虑使用gitolite.