git pull合并到非当前分支以便下游repo能够跟踪

时间:2015-02-06 04:57:01

标签: git git-pull

远程仓库有两个分支masterbr1。从中克隆本地语,并在master上签出。

使用git pull origin br1:br1命令,它会将远程br1拉入本地br1,并合并到本地master。例如:

$ git pull origin br1:br1
   e73973c..9377c16  br1        -> br1
   e73973c..9377c16  br1        -> origin/br1
Updating cca5a9b..9377c16
Fast-forward  
 file2 | 0
 file4 | 0
 2 files changed, 0 insertions(+), 0 deletions(-)

基本上发生了三件事:它将远程br1带入本地br1。它将远程br1带入本地origin/br1。然后,它会使用masterUpdating...消息显示的相同更改集更新本地Fast-forward

是否有一个命令或一些选项让它不要做"更新当前的主人"部分?

我已经阅读了一些SO问题和答案。所有这些都提出了一些命令或脚本序列。我希望可以在一个命令中完成,并进一步希望命令不是太复杂。

更新:根据以下torek解释的想法,答案是使用非标准设置:

在下游仓库中更改以下两个配置:

remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.br1.merge=refs/heads/br1

为:

remote.origin.fetch=+refs/remotes/origin/*:refs/remotes/origin/*
branch.br1.merge=refs/remotes/origin/br1

现在,在使用master作为当前分支的当前repo上,命令git pull将使br1的上游更改进入origin/br1。然后,下游仓库中的git pull将从origin/br1开始。

正常的git push命令也可以像往常一样在当前的repo和下游repo上工作。

虽然这并非完全融入非当前分支br1。但它适用于此目的。

2 个答案:

答案 0 :(得分:1)

在评论中,您暗示您希望从上游更新某个特定克隆的原因是该克隆本身是进一步下游克隆的上游。

这里至少有两种可能性,具体取决于你真正想要的结果。

第一个也许是最简单的:你可以让初始克隆成为"镜像"。 git clone

直接支持此操作
$ git clone --mirror git://github.com/git/git

--mirror标志意味着--bare,因此生成的克隆是一个裸存储库,即没有工作目录。这很重要,因为--mirror更改了默认的fetch refspec。

标准克隆

远程为origin的克隆的普通(单个)refspec读取:

[remote "origin"]
    fetch = +refs/heads/*:refs/remotes/origin/*

在这种情况下,运行git fetch origin会从上游带来所有分支,但会使用前缀refs/remotes/origin/重命名它们(例如refs/remotes/origin/masterrefs/remotes/origin/br1)。

镜像克隆

但是,在镜像克隆中,git配置文件中的refspec将显示为:

[remote "origin"]
    fetch = +refs/*:refs/*

这意味着运行git fetch会带来refs/heads/masterrefs/heads/br1之类的分支,但是当它这样做时,它会更新本地引用refs/heads/master和{{1} }。

结果是对该存储库的本地更改被删除:存储库的分支内容被替换为新的"镜像"存储库的上游。 (术语"镜像"可能有点误导,因为看镜子的人会将结果解释为左/右反转。)由于refspec源端匹配refs/heads/br1,任何标签和音符也同样被替换。

(除了refs/* refspec更改,fetch设置为remote.mirror;我不确定是什么检查这个。你可能想设置{{1也可以设置true和/或设置remote.origin.prune,以便在truefetch.prune上自动删除已在上游删除的分支,标记和其他引用操作)。

镜像的主要功能通常是作为组的单个参考点。例如,如果您有公司策略保留git树的副本fetch可用,您可能希望拥有一个正式的公司范围镜像,以便公司内的每个人都可以从镜像更新其git源的个人副本,镜像本身会定期从github版本更新。< / p>

(当一个大型子组落后于慢速网络链接时,这一点特别有用:不是几十个用户从难以到达的上游复制,而是让一个用户复制到重新分发点,然后每个人都从那里复制。)

一种非标准的镜像方法

这种纯镜像的问题在于它(必然)是git remote update克隆,因此没有人可以使用它。如果你想要的是一个可以重新克隆的常规克隆而不必“上游”两次&#34;但是,你可以这样做。

特别是,假设您对某个项目进行了初始克隆:

git

然后在此克隆中创建一个不在上游项目中的(本地)分支:

--bare

您现在拥有一个不是纯粹镜像的上游项目的副本:它在$ git clone git://github.com/some/project 分支中有自己增加的生物和技术独特性。

也可以假设,无论出于何种原因,你希望克隆这个克隆,但是能够&#34;看到&#34;原始项目的更新仅在普通$ git checkout -b xyzzy origin/master ... work and make commits ... 将其添加到此克隆时才会更新。

很难谈论所有这些克隆而不给每个克隆一个唯一的名称。 1 让我们调用原始项目Alpha,第一个克隆Beta,第二个克隆克隆Gamma。

如果您从Gamma运行xyzzy,则会看到git fetchgit ls-remote originrefs/heads/xyzzy。这里的要点是 Gamma可以看到Beta的远程跟踪分支。

如果,从Gamma,你运行:

refs/heads/master

您会看到它只有通常的标准refs/remotes/origin/master行:

$ git config --get-all remote.origin.fetch

这意味着在Gamma 上运行fetch =会丢弃它看到的所有+refs/heads/*:refs/remotes/origin/* 远程跟踪分支。 Gamma将Beta版git fetch分支复制到Gamma的refs/remotes/名称空间,但会丢弃Beta的refs/heads/条目。这是合理的:Gamma会把这些放在哪里?他们无法进入Gamma的refs/remotes/origin/名称空间。但是,您可以创建您自己的名称空间,或借用远程跟踪名称空间。

假设您要添加第二行refs/remotes/origin/行:

refs/remotes/origin/

现在,如果您在Gamma上运行fetch,Gamma将照常联系Beta,获取完整的参考列表,并将$ git config --add remote.origin.fetch '+refs/remotes/origin/*:refs/remotes/o2/*' git fetch等分支复制到masterxyzzy一样 - 但它复制Beta的远程跟踪分支机构。在这种情况下,它会将Beta版refs/remotes/origin/master复制到Gamma的名为refs/remotes/origin/xyzzy的远程跟踪分支。

一个更简单的替代方案

虽然你当然可以在Gamma上执行上述操作,但你也可以做一些更简单的事情:在Gamma上,你可以添加Alpha作为新的遥控器:

refs/remotes/origin/master

如果你检查新的远程配置,你会看到:

refs/remotes/o2/master

现在,在Gamma中,您只需运行$ git remote add alpha git://github.com/some/project 即可。 Gamma的git将直接联系Alpha并像往常一样获得其分支。这些将获得名为[remote "alpha"] url = git://github.com/some/project fetch = +refs/heads/*:refs/remotes/alpha/* git fetch alpha等的远程跟踪分支。

这个更简单的替代方案是,更简单,也可能是最好的,除非你有那种导致人们使用镜像的约束。在那种情况下,它仍然可能是最简单的有一个镜像克隆,然后有普通的克隆:镜像取代上面称为Alpha的原始上游,然后镜像的两个克隆分别是Beta和Gamma 。他们不再跟随,他们只跟随Alpha,但Alpha跟随github(或其他共享站点)上游。


1 但是请让我们抵制使用像#9; Seven of Nine&#34;这样的名字的诱惑。 : - )

答案 1 :(得分:0)

git pull命令有效地结合了git fetchgit merge *。

如果它不是当前分支,您应该使用git fetch origin然后使用git checkout br1,并将远程跟踪分支与git merge origin/br1合并。

(*实际上代替git mergegit pull将执行git rebase,具体取决于选项,当本地和远程分歧时。)