我正在编写一个git post-receive钩子,它将克隆一个单独的repo作为部署的一部分.它将repo克隆到某个文件夹,并使用-C后续git命令中的选项将目录设置为已检出的repo的目录(如手册页中所述).
当从命令行手动运行时,钩子按预期工作,但是当钩子由git运行时(即,当接收到推送时)命令失败fatal: Not a git repository: '.'.当我换出-C了--git-dir它的工作原理.
这很容易重现,创建一个裸仓库git init --bare并使用内容创建一个可执行钩子:
#!/bin/bash
set -xe
SOME_REPO_URL=???? # Some repo that is not this one
repopath=/tmp/somerepo
git clone $SOME_REPO_URL $repopath
# 1: This fails when run through the git hook
git -C $repopath checkout -b somebranch HEAD~1
# 2: This works every time
# git --git-dir $repopath/.git checkout -b somebranch HEAD~1
Run Code Online (Sandbox Code Playgroud)
从命令行运行脚本将按预期工作,但是当您推送到repo时,挂钩将失败.在两种情况下,评论1和取消评论2都有效.
我找不到任何表明这是预期行为的文档 - 我将不胜感激.
这是Ubuntu 16.04上的git 2.7.4.
字面上的区别:
git -C directory git-sub-command ...
和:
git --git-dir directory git-sub-command ...
是前端安装程序git使用操作系统级别的"更改目录"操作(os.chdir来自Python,chdir()来自C等),并$GIT_DIR为第二个设置环境变量.在任何一种情况下,它都会找到子命令并运行它.(请注意,你其实可以做两个.) 这是记录在案,包括多种效果-C选择和之间的相互作用-C和--git-dir.
然而,这只是将问题推迟到一个级别:现在你需要知道git-checkout(在git --exec-path目录中找到的)$GIT_DIR与当前工作目录的不同之处.直接答案在顶级git命令文档中,在ENVIRONMENT VARIABLES部分下:
GIT_DIR
如果GIT_DIR设置了环境变量,则它指定要使用的路径,而不是.git存储库的基础的默认值.该--git-dir命令行选项还设置这个值.
这就是JanKrüger的评论所在.当你编写一个Git钩子时,你必须意识到Git可能会为你设置一些环境变量这一事实.如果$GIT_DIR设置为相对路径名,并且您没有覆盖它,并且确实更改了目录,那么您将更改所有各种Git子命令找到存储库的方式.因此,您必须取消设置它(以获取默认的$GIT_DIR- 未设置行为),或者将其显式设置为绝对路径(以在目录更改中保留它),或者将其显式设置为path-relative或absolute-of一些其他存储库,取决于您想要的行为.
注意--work-tree集合$GIT_WORK_TREE,还有其他类似的变量,但至少在迄今为止的所有Git版本中 - $GIT_DIR是Git钩子中唯一一个"预先为你设置"(或"为你的烦恼":-)).
| 归档时间: |
|
| 查看次数: |
2940 次 |
| 最近记录: |