在子文件夹中作为git钩子的一部分运行时,为什么git命令失败?

时间:2019-05-07 13:18:55

标签: node.js git husky git-husky

我们最近将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

无论根文件夹还是子文件夹,此方法均有效,我看不出有什么区别。赫斯基应该找到.git文件夹,这似乎可以证明这一点,但是当它作为一个钩子脚本运行时,显然会有所改变。自动生成的Husky脚本的相关部分是:

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

1 个答案:

答案 0 :(得分:1)

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

the githooks documentation中有一个提示:

  

在Git调用一个钩子之前,它将其工作目录更改为裸存储库中的$ GIT_DIR或非裸存储库中工作树的根。推送期间触发的挂钩是一个例外(预接收更新后接收后更新按一下付款),它们始终在$ GIT_DIR中执行。

加上the top level Git manual page中的其他几个:

  

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

     

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

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