在git push上重置

时间:2011-04-03 17:48:06

标签: git hook reset git-post-receive

我有一个post-receive钩子脚本坐在我要推送的远程仓库上git reset --hard

这样的事情:

$ git push opal
Counting objects: 74, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (45/45), done.
Writing objects: 100% (53/53), 16.68 KiB, done.
Total 53 (delta 20), reused 0 (delta 0)
remote: warning: updating the current branch
remote: HEAD is now at 88f1e35 tweak lavalamp styles

我在这里不明白的是 - 遥控器说头部现在在XXX但是当我登录服务器时 - 远程工作副本根本没有更新!

任何想法?

3 个答案:

答案 0 :(得分:24)

问题是Git命令在为钩子脚本创建的环境中的行为与普通环境的区别。

首先,钩子脚本运行时将其当前工作目录设置为Git目录本身(即非裸存储库的.git/目录)。其次,钩子脚本使用GIT_DIR环境变量集运行并指向Git存储库(同样,非裸存储库的.git/目录)。

通常情况下,如果您尝试从git reset --hard目录运行.git/,它将会消失并显示以下消息:

fatal: This operation must be run in a work tree

但是当设置GIT_DIR时,Git命令假定当前目录是工作树。由于钩子运行时的当前目录是.git/目录,因此git reset --hard实际上将您的工作树文件“检出”到.git/而不是其父目录(即您现在有您.git/目录中的版本化内容的副本。

希望您的存储库中的任何版本化内容都没有与pathnames that Git uses in Git repositories themselves重合的路径名。如果它们一致,那么您的git reset --hard将覆盖存储库的某些内部结构,您可能希望从其他存储库重新克隆它。如果您确信没有任何版本化内容与Git的内部路径名冲突,那么您可以使用它来清理它:

# make a backup of your repository first!
(cd .git && GIT_DIR=$PWD git ls-files -cz | xargs -0 rm)

这只会删除当前跟踪的文件(它会留下已经被删除的文件,但是在破解的钩子处于活动状态时被推送的提示一次被跟踪)。


一种解决方案是将当前工作目录更改为正常工作树,并在调用Git命令之前取消设置GIT_DIR和GIT_WORK_TREE。

⋮
test "${PWD%/.git}" != "$PWD" && cd .. 
unset GIT_DIR GIT_WORK_TREE
# you can now safely use Git commands
⋮

另一个解决方案是显式重置GIT_DIR,在那里设置GIT_WORK_TREE和chdir。 Git常见问题“Why won't I see changes in the remote repo after "git push"?”建议post-update script执行此操作。链接脚本也更安全,因为如果在执行硬重置之前索引或工作树是脏的,它会产生存储。

答案 1 :(得分:15)

简而言之,使用钩子单线:

git --git-dir=. --work-tree=$PWD/.. reset --hard

更准确地说,编辑服务器上的文件.git/hooks/post-receive

#!/bin/sh
git --git-dir=. --work-tree=$PWD/.. reset --hard

设置可执行文件:

chmod +x .git/hooks/post-receive

当从客户端推送这个回购时,应该说:

HEAD is now at abcd123 comment

答案 2 :(得分:0)

脚本可能没有运行。它不会在愚蠢的http服务器上运行。 它会在ssh上运行。我不确定智能http服务器。

如果不是这样,你应该检查钩子上的'执行'permisssion(chmod + x .git / hooks / post-receive)。当你在这里时,通常会检查所有权和权限。

如果这似乎没问题,只需在脚本中添加一个logstatement作为第一行(例如date "%T $0 executed" >> /tmp/debug_hook.log)并检查日志文件以查看是否有任何更新。

此外,推送到而不是实际上可以做任何事情(一切都是最新的)。在这种情况下,钩子不被称为

是有意义的

如果所有这些都没有提示,请发布.git / config,因为它驻留在服务器上(或至少部分)。 git log -1 HEAD是否在服务器上给出了预期的结果?您的钩子脚本是否包含可能覆盖GIT_DIR,GIT_WORK_TREE或GIT_INDEX_FILE的任何内容?