【发布时间】:2017-09-06 11:56:34
【问题描述】:
我将一些代码推送到远程存储库,然后在 GitHub 上创建了第一个版本,将其命名为“v0.0.1”。 GitHub 现在显示我现在有一个版本,并且还显示在“标签”中我有一个标签“v0.0.1”。
然后我执行git pull origin master 来更新本地存储库,它返回“已经是最新的”。现在,如果我输入 git tag 什么都不会发生。那么为什么这个标签没有在本地显示呢?
【问题讨论】:
我将一些代码推送到远程存储库,然后在 GitHub 上创建了第一个版本,将其命名为“v0.0.1”。 GitHub 现在显示我现在有一个版本,并且还显示在“标签”中我有一个标签“v0.0.1”。
然后我执行git pull origin master 来更新本地存储库,它返回“已经是最新的”。现在,如果我输入 git tag 什么都不会发生。那么为什么这个标签没有在本地显示呢?
【问题讨论】:
这里的问题是git pull origin master 运行git fetch origin master,实际上是git merge origin/master。 git fetch 步骤对git fetch 提供了太多约束,从而阻止它获取您的标签。如果你自己运行git fetch origin,甚至只是运行git fetch,你将获得标签。
请注意,git pull 运行的第一个命令——git fetch origin master——使用两个单独的参数,origin 和 master,而第二个没有;相反,它有这个奇怪的斜线:git merge origin/master。这都是历史造成的:git pull 最早出现在 2005 年左右,结果证明做得太多而且做得不太好;因此,提供了一个单独的、更有用的git fetch 作为标准的面向用户的命令。大约在这个时候,“遥控器”的整个概念被发明了。 origin 这个名字本身就是这些遥控器之一。
Remotes 带有 remote-tracking 分支,而带有斜线的 origin/master 是这些远程跟踪分支之一。尽管这里有“远程”一词,但“远程跟踪分支”实际上只是您自己(本地)存储库中的另一个名称:它是您的 Git 为您记住 您的 Git 在其他(原始)Git,您的 Git 上次与他们的 Git 交谈的时间。
一开始(又是 2005 年),您必须运行 git pull <url> <branch>,这就是为什么两者是分开的。没有遥控器,也没有远程跟踪分支,所以你必须让你的 Git 通过 URL 调用他们的 Git,获取他们的分支,然后立即将结果合并到你的分支中。所以你命名了通过互联网电话调用他们的 Git 的 URL,然后命名为 他们的 分支。
你现在可以运行git fetch,根本没有参数,这将在互联网电话上调用origin(你的Git使用你的名字origin来保存URL)和获取所有内容,然后为您记住所有内容,使用标签和远程跟踪分支。在那之后,git merge完全没有参数通常会做正确的事情:如果你在master,它将合并origin/master,这是你的Git从他们的Git中记住的。但是git pull 仍然存在,部分原因是在git fetch 之后,您通常想要至少再执行一个Git 命令,而git pull 执行git fetch 然后再执行一个Git 命令——并且它仍然使用相同的旧语法:一个 URL(但现在您可以使用“远程”名称),后跟分支的名称如在该 URL 上的 Git 上看到的那样。
我对 Git 新手的建议是:永远不要使用 git pull;你的 Git 生活会更快乐。它似乎很方便,但它有所有这些陷阱,供粗心的人使用。例如,您运行的第二个命令通常应该是git rebase,而不是git merge。 找出要使用哪个命令的方法是运行git fetch,然后运行git log——但git pull 要求您提前决定是变基还是合并,之前你看看哪个会更好。
【讨论】:
origin/master 设置为 Git 所称的 upstream 分支 master(这个术语有点模棱两可,有几个不同的东西有时称为“上游”)。您可以使用git branch --set-upstream-to=origin/master master 将master 的上游设置为origin/master。之后,Git 将master 与origin/master 关联为git merge 和git rebase,没有额外的参数。 (有一些稍微短一些的命令可以做同样的事情,但这是最通用的形式。)
git clone 操作会自动将master 的上游设置为origin/master。 (也许你没有走默认流程?)