15

我有一个接收后挂钩脚本,位于我正在推送的远程仓库中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 但是当我登录服务器时 - 远程工作副本根本没有更新!

任何想法?

4

3 回答 3

25

问题在于 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/目录中拥有版本化内容的副本)。

希望您的存储库中所有版本化内容的路径名都与Git 在 Git 存储库本身中使用的路径名一致。如果它们确实一致,那么您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 常见问题解答“为什么在“git push”之后我看不到远程存储库中的更改?”</a> 建议使用一个更新后脚本来执行此操作。链接脚本也更安全,因为如果在执行硬重置之前索引或工作树是脏的,它会进行存储。

于 2011-04-04T04:11:01.893 回答
17

简而言之,使用 hook one-liner:

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

当从客户端推送到这个 repo 时,它应该这样说:

HEAD is now at abcd123 comment
于 2012-11-21T10:17:46.143 回答
0

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

如果不是这样,您应该检查钩子上的“执行”权限(chmod +x .git/hooks/post-receive)。当您使用它时,通常检查所有权和权限。

如果这看起来没问题,只需在脚本的第一行包含一个日志语句(例如date "%T $0 executed" >> /tmp/debug_hook.log)并检查日志文件以查看是否有任何更新。

此外,推送可能实际上不做任何事情(一切都是最新的)。在这种情况下,不调用钩子是有道理的

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

于 2011-04-03T23:31:35.183 回答