3

我可以使用 git 专家的一些指导,以确保对非裸存储库的推送操作安全。基本上我有一个关于如何做到这一点的计划,并且可以使用一些关于该计划是否合理的建议:)

通常,当您在 git 中推送到非裸存储库时,其工作副本和索引不会更新。正如我发现的那样,如果您忘记稍后手动更新它们,这可能会导致严重的问题!

在我们的小组中,我们有一些“中央”存储库,人们可以从中克隆和推回,但许多人也希望能够克隆他们的克隆,并根据需要以真正的分布式方式在它们之间推/拉。为了确保安全,我想确保通过“clone”或“init”创建的每个存储库都有一个自动安装的 post-receive 钩子,它将在推送操作后更新工作目录和索引以与新的头。

我发现我可以通过在 hooks 子目录中使用我的 post-receive 钩子创建一个模板目录来实现这一点,然后让我组中的每个人都执行以下操作:

git config --global init.templatedir /path/to/template/dir

目前我的 post-receive 钩子看起来像这样:

export GIT_WORK_TREE=..
git checkout -f HEAD

这似乎可以按预期工作,但我对 checkout 命令有一些不确定性。为了将工作目录和索引与 HEAD 中的状态同步,“git checkout -f HEAD”和“git reset --hard HEAD”是否等效?

我问是因为虽然我知道“git reset --hard HEAD”会做我想做的事,但在接收后挂钩中使用它会在我的测试中大大减慢推送操作(它似乎重新检查了所有文件,无论文件在工作目录中是脏的还是干净的)。“git checkout -f HEAD”似乎可以更快地完成同样的事情(给我一个干净的工作目录和与 HEAD 同步的索引),但考虑到 checkout 命令倾向于即时执行,我有点紧张与未提交的工作目录更改合并。这个命令真的会给我一个工作目录和索引,在所有情况下都与 HEAD 中的状态完全匹配(包括,例如,文件删除、重命名等)?

提前感谢您的任何建议!

4

2 回答 2

5

我可能误解了这个问题。您是否真的要设置它,以便任何人都可以在开发人员正在进行未提交的更改时推送到他的工作目录?无论如何,这都不能说是“安全的”。

大多数人所做的是拥有他们的正常工作目录,这是私有的,并将其裸克隆到同一磁盘上的公共存储库中,然后共享该存储库。这使用硬链接,因此您几乎不会使用任何额外的空间。您将更改推送到同事的公共裸仓库,当他准备好接收更改时,他会拉入他的工作目录。或者,您将更改推送到公开的裸仓库中,您的同事准备好后从那里提取。难以设置非裸存储库是有原因的。

于 2011-05-20T19:40:35.887 回答
4

我建议使用Git post-updateFAQ条目“<a href="https://git.wiki.kernel.org/index.php/GitFaq#Why_won.27t_I_see_changes_in_the_remote_repo_after_.22git_push.22.3F" rel="nofollow">为什么我在“git push”之后看不到远程仓库的变化?”。

在进行硬重置之前,它将隐藏暂存和未暂存的更改(跟踪文件)。它比普通的硬重置更安全,但正如常见问题解答条目所说,它仍然没有涵盖可能出现的所有情况(例如,无法隐藏具有预先存在的冲突的索引;它不会自动合并更改到未修改的文件git checkout,例如 dos 等)。


但是,……
如果可能的话,……
您可能应该首先避免推送到任何已签出的分支。

推送到非裸存储库是可以的,只要您不推送到签出分支(毕竟,涉及的配置变量是receive.denyCurrentBranch,而不是“<code>receive.denyNonBare”)。

上面链接的 FAQ 条目的最后一段链接到(正如 Mark Longair 在下面的评论中提到的)另一个条目,该条目概述了推送到非裸存储库的方法。该条目的动机是两个非裸存储库之间的非对称网络连接,但该技术可以应用于您需要/想要推送到非裸存储库的任何情况。

后面的 FAQ 条目给出了一个推送到远程跟踪分支的示例(在 下refs/remotes/)。只有下面的 refsrefs/heads/可以在不分离 HEAD 的情况下被检出(不使用git symoblic-ref),所以推到外面的任何东西refs/heads/应该是安全的,以避免“推到检出的分支”。

由于您在集中式环境中工作,您可能能够为此类推送的目的地制定策略。例如:

当您需要将提交推送到其他人的非裸存储库时,请将它们推送到refs/remotes/from/<your-username>/<branch>. 为了避免与正常的远程跟踪分支发生冲突,任何人都不应该定义一个名为from. 像这样推送的分支将显示在git branch -a(或-r) 中,因此可以在没有refs/remotes/前缀的情况下引用。但是,from伪远程不会出现,git remote因为没有remote.from.url配置变量。

例子:

alice$ remote add betty bettys-machine:path/to/some/non-bare/repository
alice$ git push betty master:refs/remotes/from/alice/bug/123/master

betty$ git log --reverse -p origin/master..from/alice/bug/123/master
于 2011-05-20T17:46:36.657 回答