【问题标题】:Why is `git push` to non-bare remote not the dual of `git fetch` from the remote为什么`git push`到非裸远程不是`git fetch`从远程的双重
【发布时间】:2015-09-22 21:01:11
【问题描述】:

首先,我了解与推送到非裸 git 遥控器相关的如何,包括使用 git config 选项 receive.denyCurrentBranch 和其他变通方法,所以我 寻找诸如这里的答案:

这更像是一个 git 实现/表示/哲学问题。

为什么非裸遥控器的git push <remote> 不能与遥控器的git fetch <source> 双重或基本相同?这样,我在遥控器上的本地工作目录可能已经过时(落后于新内容),我什至可能有本地更改(提前提交,甚至暂存/未暂存/隐藏/其他),但该工作目录完全不受推送操作影响?如果确实如此,那么一旦在遥控器上,我就可以合并或变基或任何必要的东西。事实上,这正是this kernel.org git faq entry 所声称的。

这样做的动机与其他提出如何问题的人完全相同:由于 {firewall , nat, security} 原因。

可能我缺少一些关于 git 如何真正跟踪“如果我只了解 XXXX”的基本知识,我会知道答案;请赐教。

【问题讨论】:

  • 可能与git pull 相比更多。您还可能会发现 stackoverflow.com/q/3329943/631619 对于更多概念性的东西很有用。直到我看到索引和暂存区域,我才自己“得到”它。在那之前,我只是一个愚蠢的 git。
  • 感谢您的指点,迈克尔。那里有一些有用的信息,而且写得很好,但这并不是我要问的。我试图具体了解为什么在推送到非裸远程时必须更新工作树。至少我认为这是正确的问题。

标签: git git-push git-fetch git-non-bare-repository


【解决方案1】:

问题是 push 会重写 refs。 HEAD 是最新签出的同义词,重写该 ref 会默默地使工作树和索引无效——该仓库中的提交将丢失推送的更改,没有任何迹象表明发生了这种情况。拒绝推送是最简单的解决方案。如果在目的地做git pull 不是一个选项,那么推到一次性并修复参考:

git push origin master:fakemaster
cd $origindir
git checkout -B master fakemaster
git branch -D fakemaster

【讨论】:

  • 感谢您的回复,虽然您的工作和我的工作实际上是等效的,但我真正想了解的是 为什么 工作树并且必须在索引时更新已更新。 IF 我了解fetch 在做什么,它正在更新引用(特别是refs/heads/master)而不更新索引或工作树。因此,为什么非裸遥控器的git push 不能做同样的事情?
  • 我想不出另一种方法来在其他人的 repo 中不同步 HEAD + index + worktree - 并且 fetch 默认情况下不会更新您的主分支,它会更新您的远程跟踪分支(在 refs/remots 中)。
  • @eggo,我认为您上述评论的答案实际上是:确实如此。 refs 得到更新,索引和工作树没有。这正是它是如何工作的。诀窍是,如果您更改当前签出的分支引用,您还会影响非裸远程的 HEAD(指向您刚刚更改的分支),这会使索引中当前的任何内容和任何更改都无效你在那个遥控器上的工作树。当然,您可以同意一个习惯,即您永远不会在该遥控器上进行更改...但是您应该首先使用裸仓库
  • @Wildcard - 谢谢你,显然我对 git 内部运作的心智模型仍然无法解决潜在的理论困惑。具体来说,工作树和索引之间的(显然)基本联系。最后,我对实际问题有了一个可行的解决方案;一个看起来类似于 jthill 的答案。实际问题是我有(N 个单独的)远程没有出站访问,但将允许入站(通过 ssh)。
  • @eggo,如果您有一个需要推送到的盒子,并且可以继续工作——只需在该盒子上创建一个用于推送的裸仓库,然后单独创建一个same 框上的非裸仓库,您可以从本地裸仓库git fetch
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-02
  • 2013-05-26
  • 1970-01-01
相关资源
最近更新 更多