1

记一次用 Git hook 提效

 3 years ago
source link: https://blog.fxcdev.com/archives/228.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

记一次用 Git hook 提效

Published on Sep 15, 2020 in Program with 0 comment

Git Shell 效率

迫于公司提交代码的要求越来越繁琐,需要写一堆信息。要命的是没有自动化工具,天天各种人肉手写 txt,改日期,改格式。经常会因为 txt 中漏写或者漏改日期导致 commit 被打回。烦不胜烦,忍无可忍,决定自己动手写一个自动化工具,把所有的格式化信息自动填入。

问题是什么?

我想要自动生成的是一个叫 ”测试重点” 的东西,这个文件由:头信息、提交信息组成。

其中 ”头信息“ 的格式是这样子的:

======================2020-09-19========================
### begin:2020-09-14
### end:2020-09-19

可以看到整个 “头信息” 都是可以自动生成的,只需要计算出本周开始和结束的日期即可。

“提交信息” 是这样子的:

---

### author:张三
### ISSUEID:AAA-111
### 模块:模块A
### 重点:操作xx发现xx,现象是xx,预期是xx。

结合我司的情况,其中 ISSUEID模块 是可以从 commit-msg 中获取的。author 可以从 git config 中获取。唯一需要填写的就是 重点 这个条目。

那么就可以梳理出解决这个问题的思路了:

通过解析 commit-msggit config,可以得到四项中的三项,剩下的一项本来我也想着从 commit-msg 中获取,但是发现对应不上,那就只能人肉填写了。最后将生成的文件和代码一起提交就行。

选择什么工具?

一开始想到的是 IDE 插件,但是实在懒得写 UI。转念一想,Git hook 非常适合这种场景:

  1. 有自动切入点,不需要手动调用
  2. 可以无障碍获取 Git 的配置和 commit-msg

分析一下我们的目的,可以总结一些特征点。

  1. 文件夹以月为单位(一个月一个文件夹)
  2. 文件以周为单位(一份文件记录一周的测试重点)
  3. 文件的主要内容可以从 commit-msg 中获取

所以我们就需要考虑以下几点:

  1. 文件会多次写入,需要考虑文件头,首次写入和后续写入的区别需要注意
  2. 需要计算一周开始和结束的日期
  3. commit-msg 中获取信息,需要用正则来筛选
  4. 选用 Git hook,那么用 shell 来实现是比较方便的
  5. Git hook 有很多时机,经过思考认为 commit-msg 是比较合适的。

从代码实现看看怎么落实这些思路。

通过计算日期得出文件名

year=$(date "+%Y");
sub_dir=$(date "+%Y-%m");
file_name=${project_name}_$(date "+%Y%m")$(expr $(expr $(date "+%d") + $(expr 6 - $(date "+%w")))).txt;

dir_path=test_focus/${year}/${sub_dir}
file_path=${dir_path}/${file_name}

创建文件前先判断文件是否存在,不存在的话就创建文件并写入文件头,否则的话就什么都不做。

create_file() {
    tmp_file_header_1="======================%s========================"
    tmp_file_header_2="### begin:%s"
    tmp_file_header_3="### end:%s"

    if [ -f ${file_path} ];then
        echo "File exist."
        else
        echo "Create file"
        mkdir -p ${dir_path}
        touch ${file_path}
        
        var_begin=$(date "+%Y-%m")-$(expr $(expr $(date "+%d") - $(date "+%w")) + 1)
        var_end=$(date "+%Y-%m")-$(expr $(expr $(date "+%d") + $(expr 6 - $(date "+%w"))))

        file_header_1=$(printf $tmp_file_header_1 $var_end)
        file_header_2=$(printf "$tmp_file_header_2" $var_begin)
        file_header_3=$(printf "$tmp_file_header_3" $var_end)

        echo ${file_header_1}>>${file_path}
        echo ${file_header_2}>>${file_path}
        echo ${file_header_3}>>${file_path}
        echo "">>${file_path}
        echo "">>${file_path}
    fi
}

写入测试重点

可以看到代码流程:

  1. 先使用正则从 commit-msg 中得到 ISSUEID
  2. 再用正则从 commit-msg 中获取到代码修改的模块
  3. 最后将信息按照规定的格式添加到文件中
get_issue() {
    issue_str=$(echo "$1" | egrep -E  '(ISSUE#([A-Za-z0-9]+-[0-9]+))' -o)
    str_arry=($(echo $issue_str | awk -F# '{print $1,$2}'))
    echo ${str_arry[1]}
}

get_module() {
    module_str=$(echo "$1" | egrep -E  '((\w+):(\w+))' -o)
    str_arry=($(echo $module_str | awk -F: '{print $1,$2}'))
    echo ${str_arry[1]}
}

add_content() {
    issue=$(get_issue $commit_msg)
    module=$(get_module $commit_msg)
    author=$(git config user.name)

    content_1="### author:$author"
    content_2="### ISSUEID:$issue"
    content_3="### 模块:$module"
    content_4="### 重点:"

    echo "---">>${file_path}
    echo "">>${file_path}
    echo ${content_1}>>${file_path}
    echo ${content_2}>>${file_path}
    echo ${content_3}>>${file_path}
    echo ${content_4}>>${file_path}
    echo "">>${file_path}
}

到这里主要实现就结束了,但是还存在一些瑕疵。

由于借助了 Git hook 的机制实现,所以存在一些瑕疵:

  • 不能在提交的时候填写 重点 条目
  • 在 Hook 触发的时候生成的文件,没有办法通过一次提交将文件和代码都提交,需要两次提交

也正是因为这些瑕疵,导致另一个致命的问题

  • 因为需要两次提交,意味着 Hook 会出发两次,出现套娃事件

这个问题有很多解决办法,我采用的是给 commit-msg 中添加标志,如果有这个标志 hook 就执行,否则 hook 不执行。

这样在第一次提交的时候打上标记,生成文件。

填写好重点后,第二次提交用 --amend 命令取出标记,正式提交。

但是上面的两点局限性还是存在的,没有办法避免。

其实这个代码方案对于别人来说可借鉴的意义并不大,分享出来主要是聊聊思路。如果有人遇到别的问题的时候,可以从这里获得一丝丝灵感,那就是最好的。

老规矩,代码在 https://gist.github.com/T-Oner/585b0d321113ac0fd6f42a39817a792f

本文由 TOner 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: Oct 21, 2020 at 10:40 am


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK