git 可以拒绝签入新行符合某些条件的文件吗?
Can git refuse to checkin files whose new lines meet some criteria?
我知道您可以配置 git 在签入文件之前通过某种验证器传递文件。
我只想对正在签入的 新 行应用验证。
这是一个具体的虚构示例。假设该项目包含一些 Javascript 文件(具有 .js
扩展名)和一些其他文件,这些文件不是 Javascript 并且具有不同的扩展名。假设引入了一个策略:新代码必须使用 let
而不是 var
,但是使用 var
的现有代码可以保留它(因为天真地将 var
更改为 let
可能会破坏东西)。
假设我们在政策引入之前的存储库中已经有 example.js
,其中包含以下内容:
function f (arg)
{
var foo = arg+1;
other_func (foo);
}
政策变更后,我们修改此文件以引入新功能;
function f (arg)
{
var foo = arg+1;
var bar = arg-1;
other_func (foo, bar);
}
两条新线是
var bar = arg-1;
other_func (foo, bar);
假设我有一个脚本 validate-js.sh
,它从标准输入中读取单独的一行 Javascript,如果输入符合策略则以状态 0 退出,否则以状态 1 退出。
将以上两行输入 validate-js.sh
将在第一行产生退出代码 1,因为 bar
被声明为 var
而不是 let
,并且第二行为 0,因为没有声明变量。但是,即使 foo
被声明为 var
, 它已经在存储库中 ,因此我们不会对该行代码进行相同的验证。
显然,一般来说,验证脚本需要访问整个文件,而不仅仅是没有上下文的个别行。
要求是,在验证失败的情况下,git 中止签入并报告一条类似于
的消息
Validation of example.js failed on line 4
git 和验证脚本如何通信并不是特别重要。例如,如果 git 以旧版本和新版本的文件名作为参数调用脚本,并在新文件中列出值得关注的行号,那就没问题了。只要不逐行对先前签入的代码应用验证,任何方法都有效。它需要在通用 Unix/Linux 系统上工作,因此假设 bash、perl 等可用。
您要做的是创建一个 git pre-commit hook
。
你的脚本看起来像这样:
#!/bin/bash
list_of_new_files=($(git diff --name-only --cached))
for file in "${list_of_files[@]}"; do
# Run you validation code here
# Print the errors for each file
# Store if validation for any file failed in $validated
done
exit $validated
只要 pre-commit
挂钩存在且状态代码非零,git 将拒绝提交。
这里是来自官方文档的an example。
然后您需要将此 git 预提交挂钩手动或作为贡献指南的一部分安装到每个 user/developer 的存储库中。您也可以在服务器端进行相同的检查,但最好尽早发现,以便开发人员可以修复他们需要的东西。
要安装挂钩,您必须将可执行文件命名为 pre-commit
,使其成为可执行文件 (chmod +x
) 并将其复制到 .git/hooks
.
我知道您可以配置 git 在签入文件之前通过某种验证器传递文件。
我只想对正在签入的 新 行应用验证。
这是一个具体的虚构示例。假设该项目包含一些 Javascript 文件(具有 .js
扩展名)和一些其他文件,这些文件不是 Javascript 并且具有不同的扩展名。假设引入了一个策略:新代码必须使用 let
而不是 var
,但是使用 var
的现有代码可以保留它(因为天真地将 var
更改为 let
可能会破坏东西)。
假设我们在政策引入之前的存储库中已经有 example.js
,其中包含以下内容:
function f (arg)
{
var foo = arg+1;
other_func (foo);
}
政策变更后,我们修改此文件以引入新功能;
function f (arg)
{
var foo = arg+1;
var bar = arg-1;
other_func (foo, bar);
}
两条新线是
var bar = arg-1;
other_func (foo, bar);
假设我有一个脚本 validate-js.sh
,它从标准输入中读取单独的一行 Javascript,如果输入符合策略则以状态 0 退出,否则以状态 1 退出。
将以上两行输入 validate-js.sh
将在第一行产生退出代码 1,因为 bar
被声明为 var
而不是 let
,并且第二行为 0,因为没有声明变量。但是,即使 foo
被声明为 var
, 它已经在存储库中 ,因此我们不会对该行代码进行相同的验证。
显然,一般来说,验证脚本需要访问整个文件,而不仅仅是没有上下文的个别行。
要求是,在验证失败的情况下,git 中止签入并报告一条类似于
的消息Validation of example.js failed on line 4
git 和验证脚本如何通信并不是特别重要。例如,如果 git 以旧版本和新版本的文件名作为参数调用脚本,并在新文件中列出值得关注的行号,那就没问题了。只要不逐行对先前签入的代码应用验证,任何方法都有效。它需要在通用 Unix/Linux 系统上工作,因此假设 bash、perl 等可用。
您要做的是创建一个 git pre-commit hook
。
你的脚本看起来像这样:
#!/bin/bash
list_of_new_files=($(git diff --name-only --cached))
for file in "${list_of_files[@]}"; do
# Run you validation code here
# Print the errors for each file
# Store if validation for any file failed in $validated
done
exit $validated
只要 pre-commit
挂钩存在且状态代码非零,git 将拒绝提交。
这里是来自官方文档的an example。
然后您需要将此 git 预提交挂钩手动或作为贡献指南的一部分安装到每个 user/developer 的存储库中。您也可以在服务器端进行相同的检查,但最好尽早发现,以便开发人员可以修复他们需要的东西。
要安装挂钩,您必须将可执行文件命名为 pre-commit
,使其成为可执行文件 (chmod +x
) 并将其复制到 .git/hooks
.