git fetch不提取远程指定的更改

时间:2017-04-05 05:11:46

标签: git github

我已经使用:

将github remote添加到我的git存储库中
git remote add --mirror=push github repository_path.git

我正在尝试使用以下方式从远程获取:

git fetch github

其中,github是我在上一步中添加的远程。

我尝试git fetch两个存储库,在第一次存储的情况下,它能够获取远程存在的更改。但是在第二次回购的情况下,git fetch无法获取远程中存在的更改。

两个存储库之间的区别在于,fetch工作的存储库是由我创建的,而fetch不工作的存储库是由其他用户创建的,但我有权在该存储库中执行pull和push

有人可以帮我解决这个问题吗?

1 个答案:

答案 0 :(得分:1)

TL; DR:--mirror=push击败了你

你可能不想要那个选项。它根本不清楚 想要的选项(如果有的话)。

讨论:提交和refspecs

首先(虽然这里不那么重要),git fetch提取提交,而不是更改。 提交和"更改"之间的(特定于Git)差异是一个提交是一个快照:一个工作树的完整副本(或者更准确地说,是在提交时在索引中的工作树的部分)。要将快照变为更改,您必须(即git diff)与其他快照进行比较。 (事实上​​,这也不太准确:git fetch提取对象,其中包括提交,但也包括带注释的标签,树和blob。但一般来说,我们&#39 ;主要关注提交。)

这里最重要的部分是:{{1>}提取的提交(以及其他对象)由 refspecs 控制。 refspec,以其第二种最简单的形式看起来像这样:

git fetch

这些是名为master:origin/master refs/heads/*:refs/remotes/foo/* origin的远程的典型fetch refspec。你的名字为foo,所以你可能想要,例如:

github

作为您的默认refspec。这告诉你的 Git,当其他 Git - 您通过互联网电话呼叫的外国Git时,在您之前指定的URL上提供{{1} },refs/heads/*:refs/remotes/github/* refs/heads/master您的 Git应该在其refs/heads/branchrefs/notes/commits分支上进行处理,并忽略{{1} } notes。

每个以冒号分隔的对的左侧是您希望Git匹配的名称。您无法控制他们的Git 提供的内容,但您可以完全控制采取的内容(即匹配)。

右侧是您希望Git在您的存储库中使用的名称。正如您在此处所看到的,您不必使用与其他Git使用的名称相同的名称。您可以使用相同的名称,如果这是您想要的名称,但您没有,并且通常您不想要到。通常,您希望将他们的分支名称(例如他们的master重命名)作为您的远程跟踪分支名称branch,例如。

我在上面提到过,这是第二种最简单的refspec形式。最简单的是没有冒号的那个,例如commits如果您使用这种无冒号的refspec形式,master不会为获取的对象提供存储库中的任何名称。这就是您所看到的。

(这再次不是100%准确:任何 origin/master写入master。但是,git fetch是一个非常临时的名称。具体而言,下一个git fetch覆盖它,因为任何 FETCH_HEAD写入FETCH_HEAD。所以它可能也是"没有名称":它&# 39;只有在下一次获取之前才有用。这就是原始git fetch脚本所需要的全部内容,当git fetch仅用于面向用户的FETCH_HEAD脚本时, "遥控器"是首先发明的。但是,当我们希望我们的远程跟踪分支更新时,它现在并不好。)

为什么git pull需要一些默认的refspecs

如果您运行git fetch,则使用 no refspec参数运行它。在这种情况下,pull会在Git配置中查找默认 refspecs。通常情况下,git fetch会为您设置这些内容:

git fetch remote

使用两个配置项创建git fetch

git remote add

(我们应该始终使用$ git remote add foo ssh://host.dom.ain/path/to/repo.git ,以防有多条已配置的remote "foo"行,但事实上$ git config --get remote.foo.url ssh://host.dom.ain/path/to/repo.git $ git config --get-all remote.foo.fetch refs/heads/*:refs/remotes/foo/* 只会设置一行。)

您使用了--get-all更改了 fetch为新远程设置的内容。它不会将git remote add设置为git remote add --mirror=push,而是将git remote add设置为remote.foo.fetch

refs/heads/*:refs/remotes/foo/*

特别是,没有remote.foo.mirror个条目。

(这个true让我们检查$ git config --get-regexp '^remote\.foo\.' remote.foo.url ssh://host.dom.ain/path/to/repo.git remote.foo.mirror true 部分下的所有内容。它是remote.foo.fetch的替代,接受任意正则表达式,我们给它一个匹配{{1}使用左锚--get-regexp并引用两个点字符以确保它们匹配文字点而不是任何单个字符。请注意,正则表达式与shell样式globs不同,并且功能更强大:{{ 1}} refspecs是shell样式的globs,而不是正则表达式。这些都不是你需要知道的东西,它只是有用的辅助信息。)

如果没有refspecs,[remote "foo"]就会陷入困境

没有命令行refspec:

--get-all

或默认remote.foo.^依赖于弱且脆弱的内置默认值。它询问其他 Git:"你最重要的分支是什么?具体来说,你的fetch承诺是什么?"然后它会根据需要提取该提交(及其历史记录),并在您的存储库中调用git fetch

git fetch github 'refs/heads/*:refs/remotes/github/*'

现在,您现在有时间到下一个remote.github.fetch使用git fetch执行某些操作。

找出你使用HEAD的原因,然后提出你真正想要的选项

FETCH_HEAD设置为From <url> * branch HEAD -> FETCH_HEAD 与在命令行上指定git fetch具有相同的效果:它强制将所有本地引用推送到在遥控器上使用相同的名称,就好像您使用了FETCH_HEAD 1 但是如果远程是与本地存储库相比的推送镜像,您可能根本不想从中获取它。 (换句话说,这个组合 - 推镜,但是可以使用 - 没有任何意义。)

1 请注意,push refspecs与fetch refspecs有所不同。两者都使用相同的语法:可选的强制标志,源引用名称或单星号glob模式,冒号和目标引用名称或类似的glob模式。但是,源和目标是相反的:对于获取,源是远程存储库/其他Git,而对于推送,源是本地存储库/我们的Git。丢失目标的含义也不同:对于提取,缺少目标意味着仅使用--mirror=push ,但对于推送,缺少目标意味着使用相同名称,例如,remote.remote.mirror表示将(我们的)主人推送到(他们的)主人。最后,fetch不允许空源,但是push会执行:这意味着要求远程Git完全删除引用