它们的名称是否相同:本地跟踪分支,相应的远程跟踪分支以及正在跟踪的相应远程分支?

时间:2015-12-31 21:39:07

标签: git

  1. 是远程跟踪分支的名称和相应的名称 被跟踪的远程分支必然相同?

    如果它们可以有不同的名称,git fetch如何匹配这两者 分支呢? (典型的refspecgit fetch+refs/heads/*:refs/remotes/remote/*

  2. 如果我是正确的,给定远程跟踪分支,我们可以创建一个 本地跟踪分支与其关联但具有不同的分支 分店名称。 (通过-b中的git checkout选项)

    此外,如果远程跟踪分支的名称和 被跟踪的相应远程分支是一样的,怎么做 git push匹配本地跟踪分支和远程分支? (典型的refspecgit push+refs/heads/*:refs/heads/*

4 个答案:

答案 0 :(得分:5)

  

远程跟踪分支的名称和跟踪的相应远程分支是否必须相同?

没有。然而,使它们不匹配会导致很多痛苦(我还没有在推动方面对它进行测试)。

  

如果它们可以有不同的名称,那么git fetch如何匹配这两个分支呢? (典型的git fetch refspec是+refs/heads/*:refs/remotes/remote/*

您可能有多条fetch =行,例如,您可以执行此操作:

[remote "strange"]
    fetch = +refs/heads/master:refs/remotes/strange/surprise
    fetch = +refs/heads/other:refs/remotes/strange/surprise2

但请注意,您不能再使用任何其他提取引用参数左侧的refs/heads/*,因为它会匹配masterother,并且(可能)将它们映射到名称除surprisesurprise2以外,git fetch除了中止,并且在这种情况下会出现错误消息。这实际上会强制您列出要从给定远程(refs/heads复制)的每个strange名称。在这种情况下。

(正如我所说,我还没有通过推送对此进行测试,而且我不知道push是否遵循与fetch相同的映射规则。最近有一些更改,在git 2.5左右,要处理"三角形"工作流程更好,例如从localmirror获取并推送到centralserver。其中一项更改是为推送添加相同类型的名称映射据推测,在这个新代码进入之前,做这种推动带来了更多的痛苦,甚至可能没有三角形的工作流程;并且可能现在它的工作效果更好......)

我们可以称之为"愚蠢的重命名技巧",我的建议是:不要使用它们。 :-)我认为他们可以正常使用大多数命令,并且与其他命令失败,但我不能指出任何特定的失败例子(只是模糊的记忆过去如何做事。)

  

如果我是正确的,给定远程跟踪分支,我们可以创建一个与之关联但具有不同分支名称的本地跟踪分支。 (通过git checkout中的-b选项)

是;这适用于各种本地工作。我再次避免使用短语"本地跟踪分支",并且只说"本地分支与上游"因为这是git文档从大约1.7开始移动的方向(见下文)。

请记住"本地分支的上游 $branch "由...产生:

  • git config --get branch.$branch.remote
  • 获取远程名称
  • 将分支名称从git config --get branch.$branch.merge映射到该远程的fetch = refspec。

因此,假设我们已创建了两个本地分支test1test2并具有以下内容:

$ 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

test1test2都引用refs/heads/test,这是其他 git存储库上的分支名称,该存储库将通过名称{ {1}}:这就是我们需要通过origin的{​​{1}}地图运行这些内容的原因。

在没有愚蠢的重命名技巧的情况下,"映射到" part将branch-name部分(fetch =之后的所有内容)保持不变,只替换中间位,以便origin变为refs/heads。这很容易做出假设。我相信一些懒惰的脚本编写者(包括我自己过去)可能已经使用了这段shell脚本代码:

refs/heads/test

不仅假设缺乏愚蠢的重命名技巧,甚至假设如果我们在分支refs/remotes/origin/test上,则上游必须是fullbranch=$(git rev-parse --symbolic-full-name $branch) || exit 1 remote=$(git config --get branch.$branch.remote) rmtbranch=refs/remotes/$remote/$branch ,而不是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/} 映射到本地存储库中的refs/heads/test

添加愚蠢的重命名技巧意味着我们根本无法轻松找到实际的上游名称,但各种命令(例如originrefs/remotes/origin/test)会自动找到正确的上游名称。为了使脚本更容易,git 1.7.0版增加了git merge符号:现在你可以简单地编写git rebase。 git解析器为您查找上游,上面(损坏的)脚本片段可以重写为:

@{upstream}

这对 fetch 来说很好,但是 push 呢?好吧,如果您正在推送到您正在提取的相同的遥控器,那么您只需做同样的事情。但是,出于各种原因,您可以将 1 拆分:从存储库 $branch@{upstream} 获取并推送到存储库 rmtbranch=$(git rev-parse --symbolic-full-name $branch@{upstream}) || exit 1 < / em>的。在这种情况下,我们可能需要 F P 不同的映射。

Git 2.5引入F,正如VonC在一些早期的SO帖子中所指出的那样,我无法随意找到,并且在github blog posting中。新的P表示法只是从上游使用 fetch 切换到使用 push 上游,即使用 @{push} 映射而不是 @{push} 映射。

还有一个好问题,这是你最后一个问题:

  

此外,如果跟踪的远程跟踪分支和相应的远程分支的名称相同,git push如何匹配本地跟踪分支和远程分支? (git push的典型refspec是P

我对git 2.5的回答,包括新的推送内容,是:我确实不知道,但你的&#34;典型的refspec&#34;不再是默认值(因为git 2.0)。当你运行没有refspec参数的F时,git会查找你的+refs/heads/*:refs/heads/*设置(以及更多可选设置,但git push实际上需要 2 )。它有五个可能的值,只有其中一个 - 不是默认值push.default

其中一个设置是push.default,该设置通过地图功能运行当前分支的refs/heads/*:refs/heads/*设置(可能是在git 2.5及更高版本中,通过新的单独推送映射如果存在,否则通过获取地图)。

1 一个原因是使用拉取请求存储库,如链接的github博客文章中所述。另一个是从本地镜像获取(如在大型企业设置中使用本地镜像用于各个分支机构),但是推送到单个中央服务器(公司指定的&#34;主站&#34;所有本地镜像的站点)实际上镜像)。

2 如果你没有设置upstream,git就会吐出很多恼人的文字。关闭它的最佳方法是设置merge,这意味着您需要&#34;必需&#34; (无论如何)设置它。而且,由于git 2.0,默认设置(如果你还没有设置)是push.default,它禁止愚蠢的重命名技巧。

答案 1 :(得分:4)

refspec

正如你所说的{。{1}}位于.git / config文件中 git配置文件包含有关refspec

的信息

enter image description here

注意

为了看到你所描述的内容,请执行以下操作:

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 ,您可以控制refspec将引用的分支。

设置跟踪分支

pull/push

enter image description here

匹配

Git v2.0发行说明

向后兼容性说明

git branch -u <upstream>/<branch name> 没有说要推送什么时,我们已经使用了 到目前为止传统的“匹配”语义(所有分支都被发送了 只要已经存在同名分支,就可以到远程控制台 在那边)。在Git 2.0中,默认是现在的“简单”语义, 推动:

  • 只有当前分支到同名的分支,并且只有 当前分支设置为与该远程集成时 分支,如果你正在推送到同一个遥控器;或

  • 只有当前分支到具有相同名称的分支,如果您 正在推送到一个不是你常去的地方的遥控器。

您可以使用配置变量git push [$there]来更改此信息 如果你是一个想要继续使用的老人 push.default语义,您可以将变量设置为“匹配”,用于 例。阅读文档以了解其他可能性。

enter image description here

答案 2 :(得分:2)

来自@codeWizard的答案是完整而完整的答案,但简单的英语答案(根据您对其答案的评论问题)是:

1 真的是两个问题。第一个答案是:不,它们不必具有相同的名称。第二个答案是:fetch实际上并不映射本地和远程分支。所有fetch确实(使用您的示例 - 默认值)是远程询问它的refs/heads/*列表以及关联的blob,并将refs存储在使用远程名称生根的refs/remotes/*中。

2 本地分支到远程分支的映射可以通过使用显式pullfetch调用来控制,也可以在.git/config中设置所有内容。在git/config中,拉动行为由$branch.merge控制,但推送由push.default控制:默认情况下,它将推送到远程上与本地相同的分支名称。如果您将其设置为upstream,那么它将使用$branch.merge作为推送目标。

操作实例:

mkdir t1 && cd t1
git init
touch file
git add file
git commit -a -m "remote"
cd ..

git clone t1 t2
cd t2
git branch -a # you should see 'master' and 'origin/master'
git branch -m master local
git pull # Should say "Already up-to-date"
git branch -a # you should now see 'local' and 'origin/master'
git push # damn! It pushed 'local' to 'origin/local'!
git push origin :local # delete 'origin/local'
git config push.default upstream # tell git to use 'local.merge' as the push target
git push # Now it should say "Everything up-to-date"

毕竟,t1配置应如下所示:

[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true

t2应如下所示:

[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
[remote "origin"]
    url = /nas/src/t/t1
    fetch = +refs/heads/*:refs/remotes/origin/*
[branch "local"]
    remote = origin
    merge = refs/heads/master
[push]
    default = upstream

答案 3 :(得分:0)

我知道这是一个老问题,但明确的答案是正确的git-config手册(输入git help configman git-config)。关于如何使用以下信息的示例就在报价之后:

  

push.default

     

定义git push应该采取的操作,如果没有显式的refspec   给出。不同的值非常适合特定的工作流程;对于   例如,在纯粹的中心

     

工作流程(即获取源等于推送目标),   上游可能就是你想要的。可能的值有:

     

·没有 - 除非refspec是,否则不要推送任何东西(错误输出)   明确给出。这主要是针对想要避免的人   始终存在的错误

     

显式的。

     

·current - 推送当前分支以使用相同的更新分支   接收端的名称。适用于中央和非中央   工作流程。

     

·upstream - 将当前分支推回到其分支   通常将更改集成到当前分支中(即   叫@ {upstream})。此模式仅

     如果你要推送到同一个存储库,

是有意义的   通常来自(即中央工作流程)。

     

·简单 - 在集中式工作流程中,像上游一样添加工作   如果上游分支的名称不同,则拒绝推送的安全性   来自当地的。

     

当推到与遥控器不同的遥控器时   通常来自,作为当前工作。这是最安全的选择   适合初学者。

     

此模式已成为Git 2.0中的默认模式。

     

·匹配 - 推送两端具有相同名称的所有分支。   这使您正在推动的存储库记住了这一组   将被推出的分支

     

(例如,如果你总是推动maint和master那里没有其他分支,   你推送的存储库将拥有这两个分支,以及你的   当地的maint和主人

     

将被推到那里。

     

要有效地使用此模式,您必须确保所有分支   在推出git push之前你会推出准备推出的,   

的全部意义      

此模式允许您一次性推送所有分支。如果   你通常只在一个分支上完成工作并推出结果,   而其他分支是

     

未完成,此模式不适合您。此模式也不合适   用于推入共享中央存储库,就像其他人可能添加的那样   那里有新的分支机构,或

     

更新您控制之外的现有分支的提示。

     

这曾经是默认设置,但不是自Git 2.0以来(简单就是新版本)   默认值)。

因此,要将git设置为适合您的配置,请输入:

git config push.default nothing

使用您的首选配置替换nothing。如果您希望它是全局的(本地计算机上的所有存储库),请添加全局选项:

git config --global push.default nothing

回答你的问题:

  1. 没有