远程跟踪分支的名称和跟踪的相应远程分支是否必须相同?
如果它们可以有不同的名称,那么git fetch两个分支如何匹配呢?(典型refspec的git fetch是+refs/heads/*:refs/remotes/remote/*)
如果我是正确的,给定远程跟踪分支,我们可以创建一个与之关联但具有不同分支名称的本地跟踪分支.(通过-b选项git checkout)
此外,如果跟踪的远程跟踪分支和相应的远程分支的名称相同,那么如何
git push匹配本地跟踪分支和远程分支?(典型refspec的git push是+refs/heads/*:refs/heads/*)
远程跟踪分支的名称和跟踪的相应远程分支是否必须相同?
不会.但是,让它们不匹配会导致很多痛苦(我没有在推动方面进行测试).
如果它们可以有不同的名称,那么git fetch如何匹配这两个分支呢?(典型的refspec
git fetch是+refs/heads/*:refs/remotes/remote/*)
你可能有多fetch =行,所以你可以这样做:
[remote "strange"]
fetch = +refs/heads/master:refs/remotes/strange/surprise
fetch = +refs/heads/other:refs/remotes/strange/surprise2
Run Code Online (Sandbox Code Playgroud)
但是请注意,你可以不再使用refs/heads/*任何额外获取refspecs的左侧,因为这将匹配master与other和(大概)将它们映射到比其他名称surprise和surprise2,并git fetch在这种情况下,终止的错误信息.这有效地强制您列出refs/heads要从给定遥控器复制的每个名称(strange在本例中).
(正如我所说的,我没有用push来测试它,我不知道push是否遵循与fetch相同的映射规则.最近有一些变化,大约2.5左右,以更好地处理"三角形"工作流程你可以从中获取localmirror并推送到centralserver其中.其中一个变化是为推送遥控器添加相同类型的名称映射.据推测,在这个新代码进入之前,做这种推动带来了更多的痛苦,可能即使没有三角形工作流程;并且可能现在它工作得更好....)
我们可能会称之为"愚蠢的重命名技巧",我的建议是:不要使用它们.:-)我认为它们可以与大多数命令一起正常工作,并且与其他命令一起失败,但我不能指出任何特定的失败例子(只是模糊的回忆我以前做过的事情).
如果我是正确的,给定远程跟踪分支,我们可以创建一个与之关联但具有不同分支名称的本地跟踪分支.(通过git checkout中的-b选项)
是; 这适用于各种本地工作.同样,我会避免使用"本地跟踪分支"这个短语,并且只是说"带有上游的本地分支",因为这是git文档自大约1.7以来的移动方向(见下文).
请记住,"本地分支的上游$branch"是由以下产生的:
git config --get branch.$branch.remotegit config --get branch.$branch.mergefetch =因此,假设我们已经创建了两个本地分支test1,test2并且具有以下内容:
$ git config --get branch.test1.remote
origin
$ git config --get branch.test1.merge
refs/heads/test
$ git config --get branch.test2.remote
origin
$ git config --get branch.test2.merge
refs/heads/test
Run Code Online (Sandbox Code Playgroud)
双方test1并test2指refs/heads/test,这是对一个分支的名称等,将通过名称定位的Git仓库origin:这就是为什么我们需要通过运行这些fetch =地图(多个)origin.
在没有愚蠢的重命名技巧的情况下,"映射通过"部分保留了分支名称部分(后面的所有内容refs/heads)不变,只是替换了中间位,因此refs/heads/test变为refs/remotes/origin/test.这很容易做出假设.我相信一些懒惰的脚本编写者(包括我自己过去)可能已经使用了这段shell脚本代码:
fullbranch=$(git rev-parse --symbolic-full-name $branch) || exit 1
remote=$(git config --get branch.$branch.remote)
rmtbranch=refs/remotes/$remote/$branch
Run Code Online (Sandbox Code Playgroud)
这不仅假设缺乏愚蠢的重命名技巧,它甚至假设如果我们在分支上test1,上游必须是origin/test1,而不是origin/test.略微不那么懒惰的脚本编写者(包括我自己过去)然后必须修复他们的脚本,例如:
fullbranch=$(git rev-parse --symbolic-full-name $branch) || exit 1
remote=$(git config --get branch.$branch.remote)
theirname=$(git config --get branch.$branch.merge)
rmtbranch=refs/remotes/$remote/${theirname#refs/heads/}
Run Code Online (Sandbox Code Playgroud)
现在假定refs/heads/test在origin地图上refs/remotes/origin/test的本地存储库中.
添加愚蠢的重命名技巧意味着我们根本无法轻易找到实际的上游名称,但各种命令(例如git merge,git rebase)会自动找到正确的上游名称.为了更容易编写脚本,git 1.7.0版增加了@{upstream}符号:你现在可以简单地编写$branch@{upstream}.git解析器为您查找上游,上面(损坏的)脚本片段可以重写为:
rmtbranch=$(git rev-parse --symbolic-full-name $branch@{upstream}) || exit 1
Run Code Online (Sandbox Code Playgroud)
这对于fetch来说都很好,但是推送呢?好吧,如果你正在推动你正在推送的同一个遥控器,那你就是做同样的事情.但是你可以为任意数量的原因,1拆起来:从存储库中取出F,并推到仓库P.在这种情况下,我们可能需要不同的映射F和P.
Git 2.5介绍@{push},正如VonC在一些早期的SO线程中所指出的那样,我无法随意找到,并在此github博客中发布.新的@{push}表示法简单地从使用上游提取切换到使用推送上游,即使用P映射而不是F映射.
还有一个很好的问题,这是你最后一个问题:
此外,如果跟踪的远程跟踪分支和相应的远程分支的名称相同,git push如何匹配本地跟踪分支和远程分支?(git push的典型refspec是
+refs/heads/*:refs/heads/*)
我对git 2.5的回答是新的推送内容:我确实不知道,但是你的"典型refspec"不再是默认值(因为git 2.0).当你git push没有refspec参数运行时,git会查找你的push.default设置(以及更多可选设置,但push.default实际上是2).它有五个可能的值,只有其中一个 - 不是默认值refs/heads/*:refs/heads/*.
其中一个设置是upstream,该设置merge通过地图功能运行当前分支的设置(可能是在git 2.5及更高版本中,通过新的单独推送映射(如果存在),或者通过获取映射).
1一个原因是使用拉取请求存储库,如链接的github博客文章中所示.另一个是从本地镜像获取(如在大型企业设置中使用本地镜像用于各个分支机构),但是推送到单个中央服务器(公司指定的"主"站点,所有本地镜像实际上都是镜像).
2如果你没有设置push.default,git会吐出很多恼人的文字.关闭它的最好方法是设置push.default,这意味着你需要(在某种意义上)"设置"它.而且,自从git 2.0以来,默认设置,如果你没有设置它,是simple禁止愚蠢的重命名技巧.
refspec正如您所说,它refspec位于您的 .git/config 文件中。
git配置文件包含有关refspec
为了查看您所描述的内容,请执行以下操作:
// Checkout master
git checkout master
// rename the master branch to a new name
git branch -m <old name> <new name>
// View the .git/config file and you will see the the new branch is still
// pointing (tracking) to the master branch, just like you described
Run Code Online (Sandbox Code Playgroud)
使用refspec可以控制pull/push要引用哪个分支。
git branch -u <upstream>/<branch name>
Run Code Online (Sandbox Code Playgroud)

Whengit push [$there]没有说明要推送什么,到目前为止我们已经使用了传统的“匹配”语义(只要那里已经有同名的分支,所有分支都会被发送到远程)。在 Git 2.0 中,默认值现在是“简单”语义,它推送:
仅当前分支到同名分支,并且仅当当前分支设置为与该远程分支集成时,如果您要推送到与提取来源相同的远程分支;或者
如果您要推送到不是您通常从中获取的远程位置,则仅将当前分支发送到具有相同名称的分支。
您可以使用配置变量push.default来更改它。例如,
如果您是想继续使用语义的老用户
,您可以将变量设置为“匹配”。matching阅读文档了解其他可能性。