4

我在一个 Web 开发人员团队中工作。我们每个人都在开发服务器的主目录中设置了一个个人网站。

我们希望将它们转换为 git 工作存储库,以便我们可以分支、变基并普遍享受 git goodness 的好处。

在在线阅读中,有两种选择:

1) 创建一个裸仓库,通过 post-receive 钩子同步到 www/ 中的工作仓库

2)直接推送到工作仓库

选项 1 的问题是它不能很好地处理分支。当我们推送除 master 以外的分支时,post-receive 挂钩仍然只同步 master,因此我们的更改永远不会出现在开发站点上。

选项 2 的问题是 git 不允许推送到签出分支以防止分离的 HEAD 状态。

在网上阅读时,选项 2 的“最佳实践”解决方案如下所示:

1)在客户端推送到虚拟分支

2) 在 SERVER 上将 dummy 合并到 master... BUZZZZ错误答案。假设最终用户没有对服务器的 shell 访问权限。

所以我想,“没问题,只需创建一个这样的帖子接收钩子”:

#!/bin/bash
read oldSHA newSHA branch
git merge $branch

现在这是奇怪的部分:当 post-receive 钩子执行时,我得到

Please, commit your changes or stash them before you can merge.

是的,我已经确认 master 是服务器上的签出分支,并且虚拟分支已正确更新。当我直接在服务器上运行相同的命令(git merge dummy)时,一切正常。

谁能解释为什么?

提前致谢。

编辑 1

这是 git status 的结果,包括合并前和合并后

Counting objects: 5, done.                                                                                                                                                            
Delta compression using up to 8 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 307 bytes, done.
Total 3 (delta 2), reused 0 (delta 0)
remote: **** PRE MERGE ****
remote: # On branch master
remote: # Untracked files:
remote: #   (use "git add <file>..." to include in what will be committed)
remote: #
remote: #       COMMIT_EDITMSG
remote: #       FETCH_HEAD
remote: #       HEAD
remote: #       ORIG_HEAD
remote: #       config
remote: #       description
remote: #       hooks/
remote: #       index
remote: #       info/
remote: #       logs/
remote: #       objects/
remote: #       packed-refs
remote: #       refs/
remote: no changes added to commit (use "git add" and/or "git commit -a")
remote: error: Your local changes to the following files would be overwritten by merge:
remote:         index.htm
remote: Please, commit your changes or stash them before you can merge.
remote: Aborting
remote: **** POST MERGE ****
remote: # On branch master
remote: # Changes not staged for commit:
remote: #   (use "git add <file>..." to update what will be committed)
remote: #   (use "git checkout -- <file>..." to discard changes in working directory)
remote: #
remote: #       modified:   index.htm
remote: #
remote: # Untracked files:
remote: #   (use "git add <file>..." to include in what will be committed)
remote: #
remote: #       COMMIT_EDITMSG
remote: #       FETCH_HEAD
remote: #       HEAD
remote: #       ORIG_HEAD
remote: #       config
remote: #       description
remote: #       hooks/
remote: #       index
remote: #       info/
remote: #       logs/
remote: #       objects/
remote: #       packed-refs
remote: #       refs/
remote: no changes added to commit (use "git add" and/or "git commit -a")

请注意,我可以手动执行 git add ., git commit -m "foo" 并以相同的结果重新执行此过程

4

1 回答 1

2

在其中一个“DUH!”中 片刻,我意识到我可以使用选项 1 并像我尝试使用选项 2 一样传递分支名称。

因此,我创建了一个 /home/username/www.git 裸存储库,将其克隆到 /home/username/www 并在 /home/username/www.git 添加了一个接收后挂钩,如下所示:

#!/bin/bash
read oldSHA newSHA branch
git --git-dir="/home/username/www/.git" --work-tree="/home/username/www" pull /home/username/www.git $branch

然后我将我的遥控器更改为 ssh://username@example.com/home/username/www.git (裸reop,而不是工作的)并通过以下方式推送到该遥控器:

git push remoteName branchName

瞧!一切正常。

实际的接收后代码更复杂,因为我对目录名称使用了一些错误陷阱和变量(因此它们可以部署给任何用户),但你明白了。

(阅读代码示例时要注意区分 www/.git 和 www.git。)

于 2013-05-09T16:46:37.803 回答