为什么 `git -C` 在 post 接收挂钩中从 Python 不起作用?

Why doesn't `git -C` work from Python in a post receive hook?

试试这个:

mkdir /tmp/one
cd /tmp/one
git init
echo -e "#!/usr/bin/env python3\nimport os\nos.system('git -C /tmp/one show')" > /tmp/one/.git/hooks/post-receive
chmod +x /tmp/one/.git/hooks/post-receive
touch test.txt
git add test.txt
git commit -m 'Initial commit'
cd /tmp/
git clone one two
cd two
git checkout -b test
echo "Why doesn't this work?" >> test.txt
git add test.txt
git commit -m "testing"
git push -u origin test

并观察非常混乱的消息:

remote: fatal: Not a git repository: '.'

什么?

说真的,到底是什么鬼?为什么这完全坏了?我可以转到不是 git 存储库 (cd / && git -C /tmp/one/show) 的文字文件夹,它工作正常。为什么这个命令不起作用?

如果我这样做也不起作用os.chdir('/tmp/one')。我无法让 post-receive 挂钩真正弄清楚到底发生了什么。它很高兴 运行 一些其他命令,比如 git merge,但它不会理解 git 显示,git 状态,或者对我来说更重要的是,git -C /tmp/one checkout master.我也试过只用裸

#!/bin/sh
git -C /tmp/one status

它给了我同样的错误信息 - not a git repostiory: '.'

知道这里到底发生了什么吗?

这里的问题是来自 Git 挂钩的命令 运行 运行 设置了各种环境变量。打你的是 $GIT_DIR,但可能还有其他人(例如,$GIT_WORK_TREE$GIT_INDEX_FILE,等等)。

它们已正确设置以处理您在挂钩时所在的存储库运行s .但是您不希望这个钩子处理这个存储库。您希望此挂钩到 chdir 其他地方并处理一些 other 存储库。届时,您应该清除不需要的环境变量,或使用 that 存储库的正确设置覆盖它们。

简而言之,添加:

unset GIT_DIR

(对于 sh/bash/etc),或在 Python 中:

del os.environ['GIT_DIR']

(注意Python版本只有在实际设置时才有效),或者在使用subprocess时使用env参数,等等