0

我们最近将一个 Node 项目移动到 mono-repo 的子文件夹中,之后我们的提交挂钩(使用 Husky 安装)由于在错​​误的目录中执行而开始失败:

{ Error: Command failed: git rev-parse HEAD
fatal: not a git repository: '.git'

    at ChildProcess.exithandler (child_process.js:297:12)
    at ChildProcess.emit (events.js:197:13)
    at maybeClose (internal/child_process.js:978:16)
    at Socket.stream.socket.on (internal/child_process.js:395:11)
    at Socket.emit (events.js:197:13)
    at Pipe._handle.close (net.js:611:12)
  killed: false,
  code: 128,
  signal: null,
  cmd: 'git rev-parse HEAD' }

我在解决问题时没有问题(基本上cd是在执行挂钩中的任何命令之前 - 进入根目录git),但我不明白为什么(未修复的)脚本在命令行上工作 - 不管哪个我执行它们的文件夹?.

脚本的失败部分基本上是:

console.log('PWD', cp.execSync('pwd'));
console.log(cp.execSync('git rev-parse HEAD'));

项目布局

.git/
frontend/
  package.json
backend/

将触发上述错误的示例命令:

git checkout master

除了错误之外,它还会打印工作目录:PWD /tmp/foo/myproj/frontend

如果我手动触发脚本,一切正常:

npm run postcheckout
PWD /tmp/foo/myproj/frontend

82dc6d2089a397f0889addb562ea84ba8d846215

无论是根文件夹还是子文件夹,这都有效,我看不出有什么区别。Husky 应该找到该.git文件夹​​,这似乎证明了这一点,但是当它作为挂钩脚本运行时,显然会发生一些变化。自动生成的 Husky 脚本的相关部分是:

cd "frontend"
...
...
npm run postcheckout
4

1 回答 1

3

TL;DR:未设置$GIT_DIR(在 sh 脚本中unset GIT_DIR)。

githooks 文档中有一个提示:

在 Git 调用钩子之前,它会将其工作目录更改为裸存储库中的 $GIT_DIR 或非裸存储库中工作树的根目录。一个例外是在推送期间触发的挂钩(pre-receiveupdatepost-receivepost-updatepush-to-checkout),它们总是在 $GIT_DIR 中执行。

加上顶级 Git 手册页中的其他一些内容:

--git-dir=<path>
设置存储库的路径。这也可以通过设置GIT_DIR环境变量来控制。它可以是当前工作目录的绝对路径或相对路径。

GIT_DIR
如果GIT_DIR设置了环境变量,则它指定要使用的路径,而不是.git存储库基础的默认路径。命令行--git-dir选项也设置此值。

这里发生的是顶级 Git程序设置为找到目录$GIT_DIR的路径。.git由于钩子已将其工作目录更改为工作树,因此 Git 程序已设置$GIT_DIR.git. 如果你chdir在其他地方,你必须$GIT_DIR适当调整——如果你 chdir 完全远离主存储库并希望让 Git再次发现 $GIT_DIR,你必须unset $GIT_DIR

于 2019-05-07T16:11:21.237 回答