git 拉取合并到非当前分支,以便下游 repo 能够跟踪
git pull to merge into non-current branch for downstream repo to be able to track
一个远程仓库有两个分支 master
和 br1
。从中克隆了一个本地文件,并在 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
。然后它使用相同的更改集更新本地 master
,由 Updating...
和 Fast-forward
消息显示。
是否有命令或一些选项让它不执行 "updating current master" 部分?
我已经阅读了一些 SO 问题和答案。所有这些都建议了一些命令或脚本序列。我希望这可以在一个命令中完成,并进一步希望该命令不要太复杂。
更新:根据下面torek解释的想法,答案是使用非标准设置:
更改下游repo中的以下两个配置:
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
命令在当前回购和下游回购上也照常工作。
虽然这并没有完全合并到非当前分支br1
。但它很适合这个目的。
git pull
命令有效地结合了 git fetch
和 git merge
*.
你应该使用 git fetch origin
然后 git checkout br1
如果它还不是当前分支,并且将远程跟踪分支与 git merge origin/br1
.
合并
(* 实际上代替 git merge
,git pull
将根据选项执行类似 git rebase
,当本地和远程有分歧时。)
在评论中,您暗示您希望从上游更新某个特定克隆的原因是该克隆本身就是下游克隆的上游。
这里至少有两种可能性,具体取决于您真正想要什么样的结果。
第一个可能是最简单的:您可以将初始克隆设为 "mirror"。 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/*
在这种情况下,运行ning git fetch origin
从上游引入所有分支,但使用前缀 refs/remotes/origin/
重命名它们(例如,refs/remotes/origin/master
和 refs/remotes/origin/br1
).
镜像克隆
然而,在镜像克隆中,git 配置文件中的 refspec 将显示为:
[remote "origin"]
fetch = +refs/*:refs/*
这意味着 运行ning git fetch
将带来像 refs/heads/master
和 refs/heads/br1
这样的分支,但是当它这样做时,它会更新本地引用 refs/heads/master
和 refs/heads/br1
.
结果是此存储库的本地更改被清除:存储库的分支内容被存储库上游的新 "mirror image" 替换。 (术语 "mirror image" 可能有点误导,因为照镜子的人会将结果解释为 left/right 反转。)由于 refspec 源端匹配 refs/*
,任何标签和注释都是同样也被替换了。
(除了 fetch
refspec 更改,remote.mirror
设置为 true
;我不确定副手是什么检查这个。你可能想设置 remote.origin.prune
到 true
,and/or 设置 fetch.prune
,这样上游删除的分支、标签和其他引用会在 fetch
或 [=43] 上自动删除=] 操作。)
镜像的主要功能通常是充当群组的单一参考点。例如,如果您有保留副本的公司政策对于 git
可用的 git 树,您可能希望有一个正式的公司范围的镜像,以便公司内的每个人都可以从镜像更新他们的 git 源的个人副本, 镜像本身从 github 版本定期更新。
(当一个大的子组位于慢速网络后面时,这特别有用 link:而不是几十个用户从难以到达的上游复制,你有一个用户复制到一个 re -分发点,然后大家从那里复制。)
很不标准的镜像方法
这种纯镜像的问题在于它(必然)是一个 --bare
克隆,因此没有人可以对其进行操作。但是,如果您想要的是无需 "look upstream twice" 即可重新克隆的常规克隆,您可以这样做。
特别是,假设您制作了某个项目的初始克隆:
$ git clone git://github.com/some/project
然后在此克隆中创建一个不在上游项目中的(本地)分支:
$ git checkout -b xyzzy origin/master
... work and make commits ...
你现在有一个上游项目的副本,它不是一个纯粹的镜像:它在 xyzzy
分支中有自己的附加生物和技术独特性。
还假设,无论出于何种原因,您希望克隆此克隆,但能够 "see" 更新原始项目 只有当它们被添加到此克隆时 通过一个普通的 git fetch
.
如果不给每个克隆一个唯一的名称,很难谈论所有这些克隆。1我们称原始项目为 Alpha,第一个克隆 Beta,第二个克隆 Gamma。
如果您从 Gamma 中 运行 git ls-remote origin
,您将看到 refs/heads/xyzzy
、refs/heads/master
和 refs/remotes/origin/master
。这里的重点是 Gamma 可以看到 Beta 的远程跟踪分支。
如果您从 Gamma 运行:
$ git config --get-all remote.origin.fetch
你会看到它只有通常的标准 fetch =
行:
+refs/heads/*:refs/remotes/origin/*
这意味着 运行ning git fetch
在 Gamma discards 它看到的所有 refs/remotes/
远程跟踪分支。 Gamma 将 Beta 的 refs/heads/
分支复制到 Gamma 的 refs/remotes/origin/
name-space,但丢弃 Beta 的 refs/remotes/origin/
条目。这很合理:Gamma 会把这些放在哪里?他们不能以 Gamma 的 refs/remotes/origin/
名字 - space 进入。但是,您可以发明您自己的名称-space,或借用远程跟踪名称-space.
假设您要添加第二个 fetch
行:
$ git config --add remote.origin.fetch '+refs/remotes/origin/*:refs/remotes/o2/*'
现在,如果您在 Gamma 上 运行 git fetch
,Gamma 将照常联系 Beta,获取完整的参考列表,并复制 master
和 xyzzy
等分支像往常一样到 refs/remotes/origin/master
和 refs/remotes/origin/xyzzy
——但它会 也 复制 Beta 的远程跟踪分支。在这种情况下,它会将 Beta 的 refs/remotes/origin/master
复制到 Gamma 的名为 refs/remotes/o2/master
.
的远程跟踪分支
一个更简单的选择
虽然您当然可以在 Gamma 上执行上述操作,但您也可以做一些更简单的事情:在 Gamma 上,您可以将 Alpha 添加为新的遥控器:
$ git remote add alpha git://github.com/some/project
如果您检查新遥控器的配置,您会看到:
[remote "alpha"]
url = git://github.com/some/project
fetch = +refs/heads/*:refs/remotes/alpha/*
现在,在 Gamma 中,您可以简单地 运行 git fetch alpha
。 Gamma的git会照常直接联系Alpha获取分支。这些将获得名为 alpha/master
、alpha/br1
等的远程跟踪分支。
这个更简单的替代方案是,嗯,更简单,而且可能是最好的,除非你有导致人们使用镜像的那种限制。那样的话,大概还是最简单的,先有一个镜像克隆,然后再有普通的克隆:镜像代替上面原来的upstream叫做Alpha,然后镜像的两个克隆分别是Beta和Gamma。他们不再相互关注,他们只关注 Alpha,但 Alpha 关注 github(或其他共享站点)上游。
1但是请让我们抵制使用像"Seven of Nine"这样的名字的诱惑:-)
一个远程仓库有两个分支 master
和 br1
。从中克隆了一个本地文件,并在 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
。然后它使用相同的更改集更新本地 master
,由 Updating...
和 Fast-forward
消息显示。
是否有命令或一些选项让它不执行 "updating current master" 部分?
我已经阅读了一些 SO 问题和答案。所有这些都建议了一些命令或脚本序列。我希望这可以在一个命令中完成,并进一步希望该命令不要太复杂。
更新:根据下面torek解释的想法,答案是使用非标准设置:
更改下游repo中的以下两个配置:
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
命令在当前回购和下游回购上也照常工作。
虽然这并没有完全合并到非当前分支br1
。但它很适合这个目的。
git pull
命令有效地结合了 git fetch
和 git merge
*.
你应该使用 git fetch origin
然后 git checkout br1
如果它还不是当前分支,并且将远程跟踪分支与 git merge origin/br1
.
(* 实际上代替 git merge
,git pull
将根据选项执行类似 git rebase
,当本地和远程有分歧时。)
在评论中,您暗示您希望从上游更新某个特定克隆的原因是该克隆本身就是下游克隆的上游。
这里至少有两种可能性,具体取决于您真正想要什么样的结果。
第一个可能是最简单的:您可以将初始克隆设为 "mirror"。 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/*
在这种情况下,运行ning git fetch origin
从上游引入所有分支,但使用前缀 refs/remotes/origin/
重命名它们(例如,refs/remotes/origin/master
和 refs/remotes/origin/br1
).
镜像克隆
然而,在镜像克隆中,git 配置文件中的 refspec 将显示为:
[remote "origin"]
fetch = +refs/*:refs/*
这意味着 运行ning git fetch
将带来像 refs/heads/master
和 refs/heads/br1
这样的分支,但是当它这样做时,它会更新本地引用 refs/heads/master
和 refs/heads/br1
.
结果是此存储库的本地更改被清除:存储库的分支内容被存储库上游的新 "mirror image" 替换。 (术语 "mirror image" 可能有点误导,因为照镜子的人会将结果解释为 left/right 反转。)由于 refspec 源端匹配 refs/*
,任何标签和注释都是同样也被替换了。
(除了 fetch
refspec 更改,remote.mirror
设置为 true
;我不确定副手是什么检查这个。你可能想设置 remote.origin.prune
到 true
,and/or 设置 fetch.prune
,这样上游删除的分支、标签和其他引用会在 fetch
或 [=43] 上自动删除=] 操作。)
镜像的主要功能通常是充当群组的单一参考点。例如,如果您有保留副本的公司政策对于 git
可用的 git 树,您可能希望有一个正式的公司范围的镜像,以便公司内的每个人都可以从镜像更新他们的 git 源的个人副本, 镜像本身从 github 版本定期更新。
(当一个大的子组位于慢速网络后面时,这特别有用 link:而不是几十个用户从难以到达的上游复制,你有一个用户复制到一个 re -分发点,然后大家从那里复制。)
很不标准的镜像方法
这种纯镜像的问题在于它(必然)是一个 --bare
克隆,因此没有人可以对其进行操作。但是,如果您想要的是无需 "look upstream twice" 即可重新克隆的常规克隆,您可以这样做。
特别是,假设您制作了某个项目的初始克隆:
$ git clone git://github.com/some/project
然后在此克隆中创建一个不在上游项目中的(本地)分支:
$ git checkout -b xyzzy origin/master
... work and make commits ...
你现在有一个上游项目的副本,它不是一个纯粹的镜像:它在 xyzzy
分支中有自己的附加生物和技术独特性。
还假设,无论出于何种原因,您希望克隆此克隆,但能够 "see" 更新原始项目 只有当它们被添加到此克隆时 通过一个普通的 git fetch
.
如果不给每个克隆一个唯一的名称,很难谈论所有这些克隆。1我们称原始项目为 Alpha,第一个克隆 Beta,第二个克隆 Gamma。
如果您从 Gamma 中 运行 git ls-remote origin
,您将看到 refs/heads/xyzzy
、refs/heads/master
和 refs/remotes/origin/master
。这里的重点是 Gamma 可以看到 Beta 的远程跟踪分支。
如果您从 Gamma 运行:
$ git config --get-all remote.origin.fetch
你会看到它只有通常的标准 fetch =
行:
+refs/heads/*:refs/remotes/origin/*
这意味着 运行ning git fetch
在 Gamma discards 它看到的所有 refs/remotes/
远程跟踪分支。 Gamma 将 Beta 的 refs/heads/
分支复制到 Gamma 的 refs/remotes/origin/
name-space,但丢弃 Beta 的 refs/remotes/origin/
条目。这很合理:Gamma 会把这些放在哪里?他们不能以 Gamma 的 refs/remotes/origin/
名字 - space 进入。但是,您可以发明您自己的名称-space,或借用远程跟踪名称-space.
假设您要添加第二个 fetch
行:
$ git config --add remote.origin.fetch '+refs/remotes/origin/*:refs/remotes/o2/*'
现在,如果您在 Gamma 上 运行 git fetch
,Gamma 将照常联系 Beta,获取完整的参考列表,并复制 master
和 xyzzy
等分支像往常一样到 refs/remotes/origin/master
和 refs/remotes/origin/xyzzy
——但它会 也 复制 Beta 的远程跟踪分支。在这种情况下,它会将 Beta 的 refs/remotes/origin/master
复制到 Gamma 的名为 refs/remotes/o2/master
.
一个更简单的选择
虽然您当然可以在 Gamma 上执行上述操作,但您也可以做一些更简单的事情:在 Gamma 上,您可以将 Alpha 添加为新的遥控器:
$ git remote add alpha git://github.com/some/project
如果您检查新遥控器的配置,您会看到:
[remote "alpha"]
url = git://github.com/some/project
fetch = +refs/heads/*:refs/remotes/alpha/*
现在,在 Gamma 中,您可以简单地 运行 git fetch alpha
。 Gamma的git会照常直接联系Alpha获取分支。这些将获得名为 alpha/master
、alpha/br1
等的远程跟踪分支。
这个更简单的替代方案是,嗯,更简单,而且可能是最好的,除非你有导致人们使用镜像的那种限制。那样的话,大概还是最简单的,先有一个镜像克隆,然后再有普通的克隆:镜像代替上面原来的upstream叫做Alpha,然后镜像的两个克隆分别是Beta和Gamma。他们不再相互关注,他们只关注 Alpha,但 Alpha 关注 github(或其他共享站点)上游。
1但是请让我们抵制使用像"Seven of Nine"这样的名字的诱惑:-)