问题:git 提交无法自动生成change-id
git push时报错,显示没有change-id
解决
方法1. 确保commit-msg正常拉取(未解决)
change-id是通过hooks/commit-msg这个文件自动成的,上图的报错提示也很明显,它想让你重新拉取这个commit-msg文件来生成change-id。
1.1 重新拉取commit-msg
# 将xxx修改为你的姓名
gitdir=$(git rev-parse --git-dir); scp -p -P 29418 xxx@gerrit.cmss.com:hooks/commit-msg ${gitdir}/hooks/
git commit --amend --no-edit
# 重新提交
git push origin HEAD:refs/for/develop
网上绝大部分方法都是这么做,但这个方法对我不奏效,推送时仍然报没有change-id。
替换别的有用的commit-msg、甚至替换hooks也不奏效。
看来问题不在commit-msg文件上。
1.2. 拉项目时确保commit-msg正常拉取
git clone "ssh://xxx@gerrit.cmss.com:29418/项目名" && scp -p -P 29418 xxx@gerrit.cmss.com:hooks/commit-msg "项目名/.git/hooks/"
如clone代码时没clone下来,请把 scp -p -P 改成 scp -O -P
git clone "ssh://xxx@gerrit.cmss.com:29418/项目名" && scp -O -P 29418 xxx@gerrit.cmss.com:hooks/commit-msg "项目名/.git/hooks/"
方法2. 手动写一个change-id(未解决)
因为change-id本质也是一串字符串,是gerrit用来标识一次变更的。
所以我在上次提交的change-id基础上改几个数字或者字符,提交上去。
这个方法在试了几次也不生效了。
由于同一个项目我copy了几份,在删掉一些复制的文件夹后突然能正常提交了,不知道是否和这个原因相关。
方法3. 删除husky(解决)
1. 拉取项目文件,正常npm install后
2.把项目目录下,.git/config文件中 huskyPath = .husky 删除
3. 删除package.json里husky相关的两行代码
可以正常提交。
看来问题就出在这个husky身上,为了弄懂原因,我也是费劲查了好久。
Husky是如何影响change-id生成的
Git hooks
首先我们知道,Git hooks 是 Git 版本控制系统中的一种机制,它在 Git 执行特定操作(如提交、合并、推送等)之前或之后自动运行自定义脚本。这些脚本可以用于代码格式化、代码检查、测试验证、安全检查等任务,以保证代码质量。
Git hooks 配置文件通常存储在仓库的 .git/hooks
目录中,每个钩子都对应一个特定事件。
Husky
Husky 是一个 Git hooks 管理工具,开发者在 package.json
文件中配置 Git hooks,而不是直接在 .git/hooks
目录中写脚本。这样多人开发时,Husky配置会随着项目一起被克隆和分发,使得Git hooks更加容易维护和管理。
对于Husky的详细工作原理,请参考文末链接。
Husky具体要使用什么文件进行git的管理和配置,可以在.git/config
文件指明。
[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true
hooksPath = .husky
首先明确,.git/config
下的core.hooksPath
的优先级比.git/hooks
高,在配置中修改了core.hooksPath
指向为.husky
后,将会使用.husky
代替.git/hooks
目录下的钩来进行检查。
.husky
├── .gitignore # 忽略 _ 目录
└── _
└── husky.sh
husky.sh文件
来看一下husky.sh文件
#!/bin/sh
if [ -z "$husky_skip_init" ]; then
debug () {
# 当 HUSKY_DEBUG 存在值为1时,开启debug
[ "$HUSKY_DEBUG" = "1" ] && echo "husky (debug) - $1"
}
readonly hook_name="$(basename "$0")"
debug "starting $hook_name..."
# 如果 HUSKY=0,则忽略hook
if [ "$HUSKY" = "0" ]; then
debug "HUSKY env variable is set to 0, skipping hook"
exit 0
fi
# 如果存在~/.huskyrc,则执行
if [ -f ~/.huskyrc ]; then
debug "sourcing ~/.huskyrc"
. ~/.huskyrc
fi
# 设置husky_skip_init=1,再次执行hook时不再进入该代码块
export readonly husky_skip_init=1
# 再次执行当前hook,其中的$0为hook路径,$@为所有参数
sh -e "$0" "$@"
exitCode="$?"
if [ $exitCode != 0 ]; then
# 打印hook执行失败信息
echo "husky - $hook_name hook exited with code $exitCode (error)"
exit $exitCode
fi
exit 0
fi
从文件中,我们可以得知如下信息:
1. 设置HUSKY_DEBUG=1开启husky的debug
# 直接在终端设置变量值,也可以在~/.bash_profile中设置为全局环境变量
HUSKY_DEBUG=1
# 执行中指定变量值
HUSKY_DEBUG=1 git commit -m "this is msg"
2. 设置HUSKY=0跳过hooks的执行,使用方法同HUSKY_DEBUG。
3. 可以通过~/.huskyrc在hook执行前执行一些命令,该文件可以自己创建。
该文件也是通过. ~/.huskyrc执行的,如果在该文件中exit 0或者exit 1都会直接结束hook,前者表示正常执行,后者表示执行失败。
husky.sh有如下的执行流程:
1. 执行hook;
2. 执行husky.sh,此时husky_skip_init=,因此执行判断内部代码。
3. husky.sh中设置husky_skip_init=1并通过sh -e "$0" "$@"再一次执行当前hook,此时因为husky_skip_init=1跳过判断内部代码,执行hooks剩余代码。
从代码上来看,这个有点绕的流程是为了获取到hook执行的结果,并在debug模式下输出。
.huskyrc文件(重点)
其中在.husky/_/husky.sh中指明:如果存在~/.huskyrc文件,则执行它。
~/.huskyrc的作用你可以理解为代替了 .git/hooks
目录下的钩子文件进行代码检查。
通过 .huskyrc 文件,可以定义各种 Git 钩子,例如 pre-commit、commit-msg 等,并指定在这些钩子触发时执行的脚本。这样,每当进行相应的 Git 操作时,Husky 会自动运行这些脚本,从而实现代码检查等功能.
# 如果存在~/.huskyrc,则执行
if [ -f ~/.huskyrc ]; then
debug "sourcing ~/.huskyrc"
. ~/.huskyrc
fi
看下这个逻辑
core.hooksPath = .husky 让我们去找
.husky/_/husky.sh文件
.husky/_/husky.sh 又指明起作用的是
.huskyrc文件
最后重点落到了
.huskyrc文件身上,而 ~/.huskyrc可以看到这是Linux系统的写法,它在找用户目录下的.huskyrc文件,我Windows系统铁是找不到这个文件的。
可以测试下:
if [ -f ~/.huskyrc ]; then
debug "sourcing ~/.huskyrc"
. ~/.huskyrc
fi
# 增加测试代码如下:
if [ ! -f ~/.huskyrc ]; then
# 若找不到.huskyrc文件,则打印以下信息
echo "--------------------huskyrc does not exist--------------."
fi
在文件目录下执行该文件,发现确实找不到huskyrc文件:
$ ./husky.sh
--------------------huskyrc does not exist--------------.
此时谜底揭开,就是因为代码提交时没有找到huskyrc文件,而huskyrc文件理应包含各种自定义钩子,这些钩子当然也包含生成change-id的功能。
都是这个huskyrc的锅!
知道了原因就很好解决了,要么配置个huskyrc文件,要么直接禁用掉husky使用原来的.git/hooks进行检查(前文方法3)。
参考文档:
Husky的详细工作原理: