了解 .git/config 的 'remote' 和 'branch' 部分
Understanding .git/config's 'remote' and 'branch' sections
这是我的 .git/config
文件的 remote
和 branch
部分的内容。
[remote "origin"]
url = https://EvanAad@bitbucket.org/EvanAad/bitbucketstationlocations.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
这些部分的内容的含义和目的是什么,特别是 fetch
和 merge
小节? Git 如何使用此信息来指导其操作?
它叫做 refspec。
它是 git 用来与远程服务器“对话”并将本地分支映射到远程分支的机制。
参考规格
refspec 将本地存储库中的分支映射到远程存储库中的分支。
这使得使用本地 Git 命令管理远程分支以及配置一些高级 git 推送和 git 获取行为成为可能。
refspec 指定为 [+]<src>:<dst>
。 <src>
参数为本地仓库中的源分支,<dst>
参数为远程仓库中的目标分支。
可选的+
标志用于强制远程存储库执行非快进更新。
Refspecs 可以与git push 命令一起使用,为远程分支指定一个不同的名称。例如,以下命令像普通 git 推送一样将 master 分支推送到原始远程仓库,但它使用 qa-master 作为原始仓库中分支的名称。这对于需要将自己的分支推送到远程仓库的 QA 团队很有用。
git push origin master:refs/heads/qa-master
通过在 Git 配置文件中添加几行,您可以使用 refspecs 来改变 git fetch 的行为。
默认情况下,git fetch
获取远程存储库中的所有分支。原因是 .git/config
文件的以下部分:
[remote "origin"]
url = https://git@github.com:mary/example-repo.git
fetch = +refs/heads/*:refs/remotes/origin/*
fetch
行告诉 git fetch 从原始仓库下载所有分支。
但是,某些工作流程并不需要所有这些。例如,许多持续集成工作流只关心 master 分支。要仅获取 master 分支,请更改获取行以匹配以下内容:
[remote "origin"]
url = https://git@github.com:mary/example-repo.git
fetch = +refs/heads/master:refs/remotes/origin/master
您也可以以类似的方式配置git 推送。例如,如果你想始终将 master 分支推送到 origin 远程的 qa-master(就像我们上面所做的那样),你可以将配置文件更改为:
[remote "origin"]
url = https://git@github.com:mary/example-repo.git
fetch = +refs/heads/master:refs/remotes/origin/master
push = refs/heads/master:refs/heads/qa-master
Refspecs 让您可以完全控制各种 Git 命令如何在存储库之间传输分支。
它们允许您从本地存储库重命名 和删除 分支,fetch/push
到具有不同名称的分支,并配置git push 和 git fetch 只使用你想要的分支。
TL;DR 总结
总的来说,我们对两三件事感兴趣:
- 如果你 运行
git fetch
没有额外的参数,会发生什么?
- 如果你 运行
git merge
或 git rebase
没有额外的参数,会发生什么?
- 如果你 运行
git pull
没有额外的参数,会发生什么?
问题 #1 的简短回答是:Git 选择您的一个 遥控器 从中获取,然后从该遥控器获取。远程 Git 选择来自 remote = <em>name</em>
部分下的 [branch]
设置。如果没有任何这样的设置,Git 使用 origin
.
问题 2 的答案是:Git 选择一些名称来使用,就好像你有 运行 git 合并 <em>name </em>
或 git 变基 <em>name</em>
。 name
基于 merge = <em>ref</em>
设置在 [branch]
部分下——但它的工作方式有点模糊:如果同一部分说,例如,remote = origin
和 branch = refs/heads/master
,名称 Git选择使用的不是 master
,而是 origin/master
。如果显示 remote = origin
和 branch = develop
,则 Git 选择的名称是 origin/develop
,依此类推。
(虽然这看起来很简单,但 Git 中的实际映射相当棘手:如果该部分显示 remote = .
和 branch = master
,则名称为 master
,不是 ./master
,例如。如果您设置了不寻常的获取 refspecs,可能会发生更多奇怪的事情。这个答案根本不涵盖最后一种情况。)
问题 #3 的答案在某些方面是最简单的:git pull
首先简单地 运行s git fetch
,然后——假设成功——其他两个命令之一, git merge
或git rebase
,所以你真的只需要看问题1和2。
长
每个 branch
部分下的 merge
条目,我认为是最不明显的。 Git 文档让它有点模糊。先说其他的吧。
[remote "..."]
部分下的设置
有很多可能的设置。通常,您不必直接使用 git config
设置它们中的任何一个——几乎所有它们都有包装命令以更“用户友好”的方式设置它们。这包括您在此处看到的两个设置。也很少有人想改变这些。
每个命名遥控器的 remote
部分,例如 origin
,列出了 git fetch
的 URL(以及可选的单独推送 URL git push
,其他 remote.*
配置项为 described in the git config
documentation)。它还有一个或多个 fetch
行,为来自该遥控器的 git fetch
提供默认的 refspec 参数。
也就是说,如果你 运行:
git fetch origin
Git 将查找 remote.origin.url
以查看连接位置,然后连接到那里,然后根据所有 remote.origin.fetch
条目检索引用。您在此处看到的默认值:
+refs/heads/*:refs/remotes/origin/*
告诉Git从远程复制所有个分支1,将它们重命名为origin/
-在您自己的存储库中添加前缀远程跟踪分支2,因此:
git fetch origin
基本上什么都拿来了。 (领先的 +
说 Git 应该这样做,无论远程跟踪分支更新是否是快进操作。也就是说,它就像使用 --force
,但不必指定 --force
.)
另一方面,如果您 运行:
git fetch origin a:b c:d
Git 将 完全忽略 所有 fetch =
行,仅从远程检索引用 a
和 c
,将它们写入存储库中的引用 b
和 d
。 (并且由于这既没有 +
也没有 --force
,其中的 none 将被强制更新——尽管在大多数情况下这没有任何区别。)
1, 2 一个 reference 是一个涵盖两个分支 和 标签的通用术语(还有更多的东西)。像 master
这样的分支名称只是以 refs/heads/
开头的引用的简写。像 origin/master
这样的远程跟踪分支名称只是以 refs/remotes/
开头的引用的简写。请注意,origin/
部分来自 fetch =
行——但要使其按预期方式工作,该行 必须 与方括号中的远程。
[branch "..."]
部分下的设置
有很多可能的设置。通常,您不必直接使用 git config
设置它们中的任何一个——几乎所有它们都有包装命令以更“用户友好”的方式设置它们。这包括您在此处看到的两个设置。想要更改其中一个或两个的情况并不少见,使用我们稍后会看到的命令。
remote
部分本身很清楚,不过:这意味着如果你在分支 master
和 运行 git fetch
上而没有给出远程名称Git 应该从名为 origin
.
的远程获取
merge
部分是棘手的部分。它列出了在远程 上看到的分支名称。注意当我们运行git fetch origin
时,我们告诉我们的Git调用另一个Git,找到另一个Git 的 master
,并将其复制到我们的存储库中,但将其命名为 origin/master
。然而……merge
行显示 merge = refs/heads/master
。它不应该说:merge = refs/remotes/origin/master
?
它可能应该——但是这个设置首先早于遥控器的发明。所以它没有;相反,它列出了参考文献的全名 ,因为它出现在遥控器上。
如果您 运行 git merge
或 git rebase
没有提供要合并或变基的分支名称,则会使用此设置。 Git 运行 通过远程 fetch =
行提供的映射来确定它应该与 origin/master
合并的名称,例如。
此设置也被git pull
便利命令使用,实际上3与运行ning git fetch
后跟运行宁git merge
.
您可能想要更改其中之一或两者。例如,如果您创建一个新的本地分支 feature/tall
,它可能根本没有 branch.feature/tall.remote
和 branch.feature/tall.merge
设置。
由于您刚刚创建了这个分支,所以没有origin/feature/tall
。 origin
上的 Git 还没有 feature/tall
,所以你没有它的副本。
然后你 git push origin feature/tall:feature/tall
让你的 Git 调用 origin
的 Git 并让他们的 Git 创建 那个分支,所以你现在 做 有 origin/feature/tall
。您可能希望 Git 记住这一点。
你 可以 运行 两个 git config
命令,但是你可以 运行 一个更高级别的包装命令:
git branch --set-upstream-to=origin/feature/tall feature/tall
这会告诉您的 Git 将 branch.feature/tall.remote
设置为 origin
,并将 branch.feature/tall.merge
设置为 refs/heads/feature/tall
(即 origin
上的名称).
您可以使用 git push -u
组合 git push
和 git branch --set-upstream-to
步骤,这更好,但这里的要点仍然存在:您使用包装器获得 both 值一次设置,因为只设置一个值不是很有用。4
特殊远程名称.
表示此存储库(与某些远程存储库相对)。如果 [branch "xyzzy"]
部分说 remote = .
和 branch = refs/heads/whatever
,那么分支 xyzzy
有 local 分支 whatever
作为它的上游,而不是将 origin/whatever
作为其上游。
3这故意掩盖了很多繁琐的细节。
4仅设置 remote
部分 会影响未来 git push
,但 git merge
和 git rebase
将无法在没有这两个条目的情况下进行远程跟踪分支映射。
这是我的 .git/config
文件的 remote
和 branch
部分的内容。
[remote "origin"] url = https://EvanAad@bitbucket.org/EvanAad/bitbucketstationlocations.git fetch = +refs/heads/*:refs/remotes/origin/* [branch "master"] remote = origin merge = refs/heads/master
这些部分的内容的含义和目的是什么,特别是 fetch
和 merge
小节? Git 如何使用此信息来指导其操作?
它叫做 refspec。 它是 git 用来与远程服务器“对话”并将本地分支映射到远程分支的机制。
参考规格
refspec 将本地存储库中的分支映射到远程存储库中的分支。
这使得使用本地 Git 命令管理远程分支以及配置一些高级 git 推送和 git 获取行为成为可能。
refspec 指定为 [+]<src>:<dst>
。 <src>
参数为本地仓库中的源分支,<dst>
参数为远程仓库中的目标分支。
可选的+
标志用于强制远程存储库执行非快进更新。
Refspecs 可以与git push 命令一起使用,为远程分支指定一个不同的名称。例如,以下命令像普通 git 推送一样将 master 分支推送到原始远程仓库,但它使用 qa-master 作为原始仓库中分支的名称。这对于需要将自己的分支推送到远程仓库的 QA 团队很有用。
git push origin master:refs/heads/qa-master
通过在 Git 配置文件中添加几行,您可以使用 refspecs 来改变 git fetch 的行为。
默认情况下,git fetch
获取远程存储库中的所有分支。原因是 .git/config
文件的以下部分:
[remote "origin"]
url = https://git@github.com:mary/example-repo.git
fetch = +refs/heads/*:refs/remotes/origin/*
fetch
行告诉 git fetch 从原始仓库下载所有分支。
但是,某些工作流程并不需要所有这些。例如,许多持续集成工作流只关心 master 分支。要仅获取 master 分支,请更改获取行以匹配以下内容:
[remote "origin"]
url = https://git@github.com:mary/example-repo.git
fetch = +refs/heads/master:refs/remotes/origin/master
您也可以以类似的方式配置git 推送。例如,如果你想始终将 master 分支推送到 origin 远程的 qa-master(就像我们上面所做的那样),你可以将配置文件更改为:
[remote "origin"]
url = https://git@github.com:mary/example-repo.git
fetch = +refs/heads/master:refs/remotes/origin/master
push = refs/heads/master:refs/heads/qa-master
Refspecs 让您可以完全控制各种 Git 命令如何在存储库之间传输分支。
它们允许您从本地存储库重命名 和删除 分支,fetch/push
到具有不同名称的分支,并配置git push 和 git fetch 只使用你想要的分支。
TL;DR 总结
总的来说,我们对两三件事感兴趣:
- 如果你 运行
git fetch
没有额外的参数,会发生什么? - 如果你 运行
git merge
或git rebase
没有额外的参数,会发生什么? - 如果你 运行
git pull
没有额外的参数,会发生什么?
问题 #1 的简短回答是:Git 选择您的一个 遥控器 从中获取,然后从该遥控器获取。远程 Git 选择来自 remote = <em>name</em>
部分下的 [branch]
设置。如果没有任何这样的设置,Git 使用 origin
.
问题 2 的答案是:Git 选择一些名称来使用,就好像你有 运行 git 合并 <em>name </em>
或 git 变基 <em>name</em>
。 name
基于 merge = <em>ref</em>
设置在 [branch]
部分下——但它的工作方式有点模糊:如果同一部分说,例如,remote = origin
和 branch = refs/heads/master
,名称 Git选择使用的不是 master
,而是 origin/master
。如果显示 remote = origin
和 branch = develop
,则 Git 选择的名称是 origin/develop
,依此类推。
(虽然这看起来很简单,但 Git 中的实际映射相当棘手:如果该部分显示 remote = .
和 branch = master
,则名称为 master
,不是 ./master
,例如。如果您设置了不寻常的获取 refspecs,可能会发生更多奇怪的事情。这个答案根本不涵盖最后一种情况。)
问题 #3 的答案在某些方面是最简单的:git pull
首先简单地 运行s git fetch
,然后——假设成功——其他两个命令之一, git merge
或git rebase
,所以你真的只需要看问题1和2。
长
每个 branch
部分下的 merge
条目,我认为是最不明显的。 Git 文档让它有点模糊。先说其他的吧。
[remote "..."]
部分下的设置
有很多可能的设置。通常,您不必直接使用 git config
设置它们中的任何一个——几乎所有它们都有包装命令以更“用户友好”的方式设置它们。这包括您在此处看到的两个设置。也很少有人想改变这些。
每个命名遥控器的 remote
部分,例如 origin
,列出了 git fetch
的 URL(以及可选的单独推送 URL git push
,其他 remote.*
配置项为 described in the git config
documentation)。它还有一个或多个 fetch
行,为来自该遥控器的 git fetch
提供默认的 refspec 参数。
也就是说,如果你 运行:
git fetch origin
Git 将查找 remote.origin.url
以查看连接位置,然后连接到那里,然后根据所有 remote.origin.fetch
条目检索引用。您在此处看到的默认值:
+refs/heads/*:refs/remotes/origin/*
告诉Git从远程复制所有个分支1,将它们重命名为origin/
-在您自己的存储库中添加前缀远程跟踪分支2,因此:
git fetch origin
基本上什么都拿来了。 (领先的 +
说 Git 应该这样做,无论远程跟踪分支更新是否是快进操作。也就是说,它就像使用 --force
,但不必指定 --force
.)
另一方面,如果您 运行:
git fetch origin a:b c:d
Git 将 完全忽略 所有 fetch =
行,仅从远程检索引用 a
和 c
,将它们写入存储库中的引用 b
和 d
。 (并且由于这既没有 +
也没有 --force
,其中的 none 将被强制更新——尽管在大多数情况下这没有任何区别。)
1, 2 一个 reference 是一个涵盖两个分支 和 标签的通用术语(还有更多的东西)。像 master
这样的分支名称只是以 refs/heads/
开头的引用的简写。像 origin/master
这样的远程跟踪分支名称只是以 refs/remotes/
开头的引用的简写。请注意,origin/
部分来自 fetch =
行——但要使其按预期方式工作,该行 必须 与方括号中的远程。
[branch "..."]
部分下的设置
有很多可能的设置。通常,您不必直接使用 git config
设置它们中的任何一个——几乎所有它们都有包装命令以更“用户友好”的方式设置它们。这包括您在此处看到的两个设置。想要更改其中一个或两个的情况并不少见,使用我们稍后会看到的命令。
remote
部分本身很清楚,不过:这意味着如果你在分支 master
和 运行 git fetch
上而没有给出远程名称Git 应该从名为 origin
.
merge
部分是棘手的部分。它列出了在远程 上看到的分支名称。注意当我们运行git fetch origin
时,我们告诉我们的Git调用另一个Git,找到另一个Git 的 master
,并将其复制到我们的存储库中,但将其命名为 origin/master
。然而……merge
行显示 merge = refs/heads/master
。它不应该说:merge = refs/remotes/origin/master
?
它可能应该——但是这个设置首先早于遥控器的发明。所以它没有;相反,它列出了参考文献的全名 ,因为它出现在遥控器上。
如果您 运行 git merge
或 git rebase
没有提供要合并或变基的分支名称,则会使用此设置。 Git 运行 通过远程 fetch =
行提供的映射来确定它应该与 origin/master
合并的名称,例如。
此设置也被git pull
便利命令使用,实际上3与运行ning git fetch
后跟运行宁git merge
.
您可能想要更改其中之一或两者。例如,如果您创建一个新的本地分支 feature/tall
,它可能根本没有 branch.feature/tall.remote
和 branch.feature/tall.merge
设置。
由于您刚刚创建了这个分支,所以没有origin/feature/tall
。 origin
上的 Git 还没有 feature/tall
,所以你没有它的副本。
然后你 git push origin feature/tall:feature/tall
让你的 Git 调用 origin
的 Git 并让他们的 Git 创建 那个分支,所以你现在 做 有 origin/feature/tall
。您可能希望 Git 记住这一点。
你 可以 运行 两个 git config
命令,但是你可以 运行 一个更高级别的包装命令:
git branch --set-upstream-to=origin/feature/tall feature/tall
这会告诉您的 Git 将 branch.feature/tall.remote
设置为 origin
,并将 branch.feature/tall.merge
设置为 refs/heads/feature/tall
(即 origin
上的名称).
您可以使用 git push -u
组合 git push
和 git branch --set-upstream-to
步骤,这更好,但这里的要点仍然存在:您使用包装器获得 both 值一次设置,因为只设置一个值不是很有用。4
特殊远程名称.
表示此存储库(与某些远程存储库相对)。如果 [branch "xyzzy"]
部分说 remote = .
和 branch = refs/heads/whatever
,那么分支 xyzzy
有 local 分支 whatever
作为它的上游,而不是将 origin/whatever
作为其上游。
3这故意掩盖了很多繁琐的细节。
4仅设置 remote
部分 会影响未来 git push
,但 git merge
和 git rebase
将无法在没有这两个条目的情况下进行远程跟踪分支映射。