当 运行 作为子文件夹中 git 挂钩的一部分时,为什么 `git` 命令会失败?
Why does `git` commands fail when run as part of a git hook in a subfolder?
我们最近将一个 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
-ing 到根目录,然后在挂钩中执行任何 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
文件夹,这似乎证明了这一点,但显然当它是 运行 作为 hook 脚本时,情况发生了变化。自动生成的 Husky 脚本的相关部分是:
cd "frontend"
...
...
npm run postcheckout
- fatal: Not a git repository: '.git' error
- https://github.com/typicode/husky/issues/348
- https://github.com/typicode/husky/issues/167
TL;DR: 取消设置 $GIT_DIR
(在 sh 脚本中,unset GIT_DIR
)。
the githooks documentation中有提示:
Before Git invokes a hook, it changes its working directory to either $GIT_DIR in a bare repository or the root of the working tree in a non-bare repository. An exception are hooks triggered during a push (pre-receive, update, post-receive, post-update, push-to-checkout) which are always executed in $GIT_DIR.
加上 the top level Git manual page 中的另外几个:
--git-dir=<path>
Set the path to the repository. This can also be controlled by setting the GIT_DIR
environment variable. It can be an absolute path or relative path to current working directory.
GIT_DIR
If the GIT_DIR
environment variable is set then it specifies a path to use instead of the default .git
for the base of the repository. The --git-dir
command-line option also sets this value.
这里发生的是顶层Git 程序 将$GIT_DIR
设置为.git
目录所在的路径成立。由于挂钩已将其工作目录更改为 work-tree,因此 Git 程序已将 $GIT_DIR
设置为 .git
。如果你在别处 chdir
,你必须适当地调整 $GIT_DIR
——如果你 chdir 完全远离主存储库并希望 Git discover $GIT_DIR
再次,您必须 unset $GIT_DIR
.
我们最近将一个 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
-ing 到根目录,然后在挂钩中执行任何 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
文件夹,这似乎证明了这一点,但显然当它是 运行 作为 hook 脚本时,情况发生了变化。自动生成的 Husky 脚本的相关部分是:
cd "frontend"
...
...
npm run postcheckout
- fatal: Not a git repository: '.git' error
- https://github.com/typicode/husky/issues/348
- https://github.com/typicode/husky/issues/167
TL;DR: 取消设置 $GIT_DIR
(在 sh 脚本中,unset GIT_DIR
)。
the githooks documentation中有提示:
Before Git invokes a hook, it changes its working directory to either $GIT_DIR in a bare repository or the root of the working tree in a non-bare repository. An exception are hooks triggered during a push (pre-receive, update, post-receive, post-update, push-to-checkout) which are always executed in $GIT_DIR.
加上 the top level Git manual page 中的另外几个:
--git-dir=<path>
Set the path to the repository. This can also be controlled by setting theGIT_DIR
environment variable. It can be an absolute path or relative path to current working directory.
GIT_DIR
If theGIT_DIR
environment variable is set then it specifies a path to use instead of the default.git
for the base of the repository. The--git-dir
command-line option also sets this value.
这里发生的是顶层Git 程序 将$GIT_DIR
设置为.git
目录所在的路径成立。由于挂钩已将其工作目录更改为 work-tree,因此 Git 程序已将 $GIT_DIR
设置为 .git
。如果你在别处 chdir
,你必须适当地调整 $GIT_DIR
——如果你 chdir 完全远离主存储库并希望 Git discover $GIT_DIR
再次,您必须 unset $GIT_DIR
.