先看需求:在美术或者策划提交一个新的资源时,经常会只提交了资源而没提交对应meta文件,导致后面冲突泛滥,因此需要一个git的提交钩子来帮助告诉他们需要提交对应的meta文件,否则强制提交失败。

  利用git hooks 可以快速完成这个需求,代码如下:

 1 # 检查art目录下所有资源的meta情况
 2 declare -A assetMap
 3 declare -A assetMetaMap
 4 
 5 for i in $tagList;
 6 do
 7     assetfileNames=$(git diff --cached --name-only  --diff-filter=$i -- 'client/UnityProject/Assets/arts/*.*')
 8     assetMetafileNames=$(git diff --cached --name-only  --diff-filter=$i -- 'client/UnityProject/Assets/arts/*.*.meta')
 9     # 其实这里需要跟上面asset一样考虑路径中有中文然后出现双引号的问题;不过美术资源一般不会有中文名,而且美术用sourceTree提交的比较多,用sourceTree不会出这个问题
10     for key in $assetfileNames;do
11         case "$key" in
12             *.meta) ;; # 因为*.*会匹配到meta文件,所以这边做一个过滤
13             *)
14                 assetMap["$key"]=$i
15                 echo $key $i;;
16         esac
17     done
18     for key in $assetMetafileNames;do
19         assetMetaMap["$key"]=$i
20         echo $key $i
21     done
22 done
23 
24 for key in ${!assetMetaMap[*]};
25 do
26     if [ "${assetMetaMap["$key"]}" = "M" ]; then
27         echo $key 你不能修改一个meta文件!
28         exit 1
29     fi
30     if [ "${assetMetaMap["$key"]}" != "${assetMap["${key:0:${#key}-5}"]}" ]; then
31         echo $key 美术资源的meta和资源 状态不一致,可能是你新增或者删除了一个meta文件,但是没有提交对应的资源文件
32         exit 1
33     fi
34 done
35 
36 for key in ${!assetMap[*]};
37 do
38     if [ "${assetMap["$key"]}" != "M" ]; then
39         if [ "${assetMap["$key"]}" != "${assetMetaMap["${key}.meta"]}" ]; then
40             echo $key 美术资源的meta和资源 状态不一致,可能是你新增或者删除了一个资源文件,但是没有提交对应的meta文件
41             exit 1
42         fi
43     fi
44 done
45 
46 echo arts文件夹下资源和对应meta校验完成
View Code

 

  相关资料集合:

  git hooks 概述:链接

  git diff 相关指令:https://www.runoob.com/git/git-diff.html

  shell相关教程:https://www.runoob.com/linux/linux-shell-variable.html

  git hooks 本地脚本如何push到远程:https://zhuanlan.zhihu.com/p/383513484

  

  关于上面的第四个问题,如何push到远程,实际上他的方法不太方便,不如在类静态构造器内或者打开编辑器的时候直接复制对应文件来的方便。(不过Unity中静态构造器的调用时机很奇怪..可能跟版本有关系?)

  

  代码临时写的(甚至有魔法数字26,反正意思就是根据Assets路径回到git的根目录,可以根据实际工程修改代码),大概就是在初始化的时候拷贝版本记录内的hooks文件到.git下面,来避免.git中文件只能本地使用的问题。

  最后效果,如果只提交了资源但是没提交meta,会强制报错。

  

 ------------------------------------后来的分割线------------------------------------

  另外一个可能出现的问题是,在命令行的情况下中文字符会被转化成\xxx,因此会在路径前后带双引号,导致出问题,在处理的时候需要把引号去掉(不过sourceTree下不会出现这个问题,因为中文能被正确的显示)。

  可以参考下面利用case的形式进行处理:

 1 # 首先检查asset和meta的关系
 2 declare -A assetMap
 3 declare -A assetMetaMap
 4 
 5 tagList=("A D M R")
 6 
 7 for i in $tagList;
 8 do
 9     assetfileNames=$(git diff --cached --name-only  --diff-filter=$i -- 'client/UnityProject/Assets/Tools/SSSEditor/*.asset')
10     assetMetafileNames=$(git diff --cached --name-only  --diff-filter=$i -- 'client/UnityProject/Assets/Tools/SSSEditor/*.asset.meta')
11     # 在命令行环境下(cmd或者vscode),中文会以\xxx的形式出现,所以有双引号包含,这里需要处理这种特殊情况
12     # sourceTree下中文可以直接显示,没有这个问题
13     for key in $assetfileNames;do
14         realName=$key
15         sign='"'
16         case "$key" in
17             *$sign) realName="${key:1:${#key}-2}";; 
18             *) ;;
19         esac
20         assetMap["$realName"]=$i
21         echo $realName $i
22     done
23     for key in $assetMetafileNames;do
24         realName=$key
25         sign='"'
26         case "$key" in
27             *$sign) realName="${key:1:${#key}-2}";; 
28             *) ;;
29         esac
30         assetMetaMap["$realName"]=$i
31         echo $realName $i
32     done
33 done
34 
35 for key in ${!assetMetaMap[*]};
36 do
37     if [ "${assetMetaMap["$key"]}" = "M" ]; then
38         echo $key 你不能修改一个meta文件!
39         exit 1
40     fi
41     if [ "${assetMetaMap["$key"]}" != "${assetMap["${key:0:${#key}-5}"]}" ]; then
42         echo $key asset.meta和assert 状态不一致,可能是你新增或者删除了一个meta文件,但是没有提交对应的资源文件
43         exit 1
44     fi
45 done
46 
47 for key in ${!assetMap[*]};
48 do
49     if [ "${assetMap["$key"]}" != "M" ]; then
50         if [ "${assetMap["$key"]}" != "${assetMetaMap["${key}.meta"]}" ]; then
51             echo $key asset.meta和assert 状态不一致,可能是你新增或者删除了一个资源文件,但是没有提交对应的meta文件
52             exit 1
53         fi
54     fi
55 done
56 
57 echo asset.meta和assert校验完成
View Code

  

  顺带一提,这个代码其实是在上面那个代码之前的,所以前面代码没有的tagList可以在这里找到。