如何处理多个遥控器和分支机构
How to deal with multiple remotes and branches
我想要多个远程服务器,它们应该为所有分支相互镜像。
开始这次冒险,我发现:
pull/push from multiple remote locations
这告诉我:
$ git remote set-url origin --push --add <a remote>
$ git remote set-url origin --push --add <another remote>
如果我做一个
$ git pull --all
Fetching origin
Fetching willi
看起来不错!
但是推送没有用:
$ git push --all
To ssh://gitmini@localhost/home/gitmini/gitrepos/repo1
f974ce2..c146f0a master -> master
没有推送到我的第二个遥控器!为什么?
所以如果我尝试不同的方法,例如:
$ git remote add mirroring ssh://gitmini@localhost/home/gitmini/gitrepos/repo2
$ git remote set-url mirroring --push --add ssh://gitmini@localhost/home/gitmini/gitrepos/repo1
$ git remote -vv
mirroring ssh://gitmini@localhost/home/gitmini/gitrepos/repo2 (fetch)
mirroring ssh://gitmini@localhost/home/gitmini/gitrepos/repo1 (push)
这真是出乎我的意料!
还有一个额外的选项 --mirror=fetch|pull
但这也会导致错误配置的结果。
正如某些评论中提到的,如果命令重复,则可以添加 url。但我永远不能添加超过一个回购协议来获取。作为例子,我可以得到这个结果,在我看来充其量是错误的:
$ git remote -vv
mirroring ssh://gitmini@localhost/home/gitmini/gitrepos/repo1 (fetch)
mirroring ssh://gitmini@localhost/home/gitmini/gitrepos/repo2 (push)
mirroring ssh://gitmini@localhost/home/gitmini/gitrepos/repo1 (push)
mirroring ssh://gitmini@localhost/home/gitmini/gitrepos/repo2 (push)
作为下一次尝试我 运行:
$ git config -e
并添加了以下部分:
[remote "mirroring"]
url = ssh://gitmini@localhost/home/gitmini/gitrepos/repo1
fetch = +refs/heads/*:refs/remotes/mirroring/*
pushurl = ssh://gitmini@localhost/home/gitmini/gitrepos/repo1
url = ssh://gitmini@localhost/home/gitmini/gitrepos/repo2
fetch = +refs/heads/*:refs/remotes/mirroring/*
pushurl = ssh://gitmini@localhost/home/gitmini/gitrepos/repo2
但是
$ git remote -vv
mirroring ssh://gitmini@localhost/home/gitmini/gitrepos/repo1 (fetch)
mirroring ssh://gitmini@localhost/home/gitmini/gitrepos/repo1 (push)
mirroring ssh://gitmini@localhost/home/gitmini/gitrepos/repo2 (push)
获取 repo2
的行被忽略了!
事实上,我无法设置配置。我的任务很简单:同步两个遥控器。
编辑:对 torek 给定答案的一些评论:
看来可以设置:
[remote "mirroring"]
url = ssh://gitmini@localhost/home/gitmini/gitrepos/repo1
fetch = +refs/heads/*:refs/remotes/mirroring/*
pushurl = ssh://gitmini@localhost/home/gitmini/gitrepos/repo1
url = ssh://gitmini@localhost/home/gitmini/gitrepos/repo2
fetch = +refs/heads/*:refs/remotes/mirroring/*
pushurl = ssh://gitmini@localhost/home/gitmini/gitrepos/repo2
有了这个配置
$ git push mirroring
...
To ssh://gitmini@localhost/home/gitmini/gitrepos/repo1
...
To ssh://gitmini@localhost/home/gitmini/gitrepos/repo2
结果推送到两个遥控器。
我不知道这个配置是否有效。
托雷克写道:
If you configure more than one, only one of them works, all the others are ignored.
好像不是真的。在我给定的配置中,所有遥控器都将按照我上面的示例通过推拉访问。
事实上,配置为 [remotes]
的组看起来对我的用例非常有用!
远程和获取
Git 可以有很多 "remote",所以当你做 git config -e
时,你会看到这样的东西:
[remote "r1"]
url = ...
fetch = +refs/heads/*:refs/remotes/r1/*
[remote "r2"]
url = ...
fetch = +refs/heads/*:refs/remotes/r2/*
然而,任何一个遥控器只能有一个 url
(最多一个pushurl
)。如果您配置了多个,则只有一个有效,其他的都将被忽略。
(有点奇怪,任何一个遥控器都可以有许多 fetch
条目,并且所有条目都被遵守。此外,您可以在此处设置 push =
以设置默认推送 refspec,尽管我有我自己从来没有用过这个。)
当你 运行 git fetch
你可以命名 一个特定的 远程:
$ git fetch r1
[fetches from r1]
$ git fetch r2
[fetches from r2]
或名称 多个 遥控器使用 --multiple
:
$ git fetch --multiple r1 r2
[fetches from r1 and r2]
或来自所有 遥控器:
$ git fetch --all
[fetches from r1, r2, and any other defined remote]
或来自 "groups",稍后我将对其进行定义。 --multiple
标志使 git fetch
将其所有参数视为远程或组名称。否则,远程名称之后的每个参数都被视为 refspec(例如,git fetch r1 r2
,没有 --all
,意味着从远程 r1
获取 ref r2
)。
A "group" 是定义的东西,例如:
[remotes]
somegroup = r1 r2
您在左侧列出了组,在右侧列出了它表示的一组遥控器。请注意,这是 remotes,复数形式,您可以使用 git config remotes.somegroup r1 r2
设置它,尽管当事情变得如此复杂时,我更喜欢只使用 git config -e
和我的编辑器,这样我就可以一起看到所有的东西了。
使用此集合,您可以 运行 git fetch somegroup
,它将从 r1
和 r2
.
中获取
您还可以 运行 git remote update
,默认情况下从您的所有遥控器中获取,但可以配置(通过 remotes.groups
项目以及 remotes.default
)获取来自特定组或单个远程。
推送
使用git push
时,您只能推送到一个远程。要推送到多个遥控器,您必须 运行 几个 git push
es。
(git push --all
并不意味着推送到所有遥控器,而是推送所有参考,就好像您将 refs/*:refs/*
作为参考规范一样。)
Refspecs,或者获取或推送的内容
fetch
和 push
都使用 "refspecs" 来确定他们的工作方式。
完整的 refspec 看起来像您在 remotes 下的 fetch =
行中看到的那些,例如:
+refs/heads/*:refs/remotes/r1/*
有一个可选的前导 +
符号,它设置强制标志(您可以使用 --force
设置相同的标志),然后是两个引用(例如 refs/heads/master
或 refs/tags/v1.1
) 以冒号 :
字符分隔。星号 *
可能会出现,它的工作方式有点像 shell 通配符,只是当它位于 右侧 一侧时,它表示 "use whatever the one on the left side matched"。 (它也不能出现在任意位置;通常你希望它紧跟在 /
之后,如 refs/heads/*
或 refs/*
。)
提取和推送命令不太对称。当做fetch
时,左边的名称或模式是为遥控器的参考,右边的名称是必要的1,因为它告诉git如何重塑本地存储库的名称。这就是为什么远程 origin
的获取行在右边读取 refs/remotes/origin/*
的原因,例如:我们想重新塑造他们所有的 refs/heads/*
引用——他们所有的分支——成为我们的refs/remotes/
中的远程跟踪分支,并放置在 origin/
.
下
与 git push
但是, 左侧的名称或模式 供您自己参考 - 您的分支、标签、注释或其他任何内容 - 以及名称右边是遥控器。如果省略右侧名称,通常表示 "use the same name on the remote"。因此 refs/heads/master
(没有加号也没有冒号)表示 "push my branch master
to the remote's master
".
(我认为——仅代表我的意见,并非技术要求——最好在定义推送规范的配置文件中使用冒号并在左右两边都明确,即使你可以省略右侧。)
镜像
"Mirroring" 在 git 中有特定的含义,尽管事实证明它有两个不同的含义(fetch
镜像 vs push
镜像)。具体意思就是"set the fetch or pull refspec to copy all references"。例如:
$ git remote add --mirror=fetch foo ssh://foo.foo/foo/foo.git
导致 git 放置:
[remote "foo"]
url = ssh://foo.foo/foo/foo.git
fetch = +refs/*:refs/*
进入配置文件。 (奇怪的是,在这个配置下不会设置 prune = true
。它可能应该设置,但是你可以 运行 git remote update foo --prune
或 git fetch -p foo
来获得相同的效果。)或者:
$ git remote add --mirror=push foo ssh://foo.foo/foo/foo.git
配置:
[remote "foo"]
url = ssh://foo.foo/foo/foo.git
mirror = true
(请参阅 git push
文档)。
请注意,为多个远程设备设置 mirror=fetch 意义不大。例如,假设您为遥控器 r1
和 r2
设置了此项。当您从远程 r1
获取作为获取镜像时,您会清除所有分支和标签,并用来自 r1
的分支和标签替换它们。然后,你从 r2
获取作为获取镜像,清除从 r1
复制的所有分支和标签,用来自 r2
的分支和标签替换它们。 r1
fetch 在这种情况下有什么好处?
1如果您省略右侧,fetch
将无法更新您的任何参考资料。这将是完全无用的,除了有一个历史模式,仍然被 pull
脚本使用,其中获取的引用存放在 FETCH_HEAD
文件中。
我想要多个远程服务器,它们应该为所有分支相互镜像。
开始这次冒险,我发现: pull/push from multiple remote locations
这告诉我:
$ git remote set-url origin --push --add <a remote>
$ git remote set-url origin --push --add <another remote>
如果我做一个
$ git pull --all
Fetching origin
Fetching willi
看起来不错!
但是推送没有用:
$ git push --all
To ssh://gitmini@localhost/home/gitmini/gitrepos/repo1
f974ce2..c146f0a master -> master
没有推送到我的第二个遥控器!为什么?
所以如果我尝试不同的方法,例如:
$ git remote add mirroring ssh://gitmini@localhost/home/gitmini/gitrepos/repo2
$ git remote set-url mirroring --push --add ssh://gitmini@localhost/home/gitmini/gitrepos/repo1
$ git remote -vv
mirroring ssh://gitmini@localhost/home/gitmini/gitrepos/repo2 (fetch)
mirroring ssh://gitmini@localhost/home/gitmini/gitrepos/repo1 (push)
这真是出乎我的意料!
还有一个额外的选项 --mirror=fetch|pull
但这也会导致错误配置的结果。
正如某些评论中提到的,如果命令重复,则可以添加 url。但我永远不能添加超过一个回购协议来获取。作为例子,我可以得到这个结果,在我看来充其量是错误的:
$ git remote -vv
mirroring ssh://gitmini@localhost/home/gitmini/gitrepos/repo1 (fetch)
mirroring ssh://gitmini@localhost/home/gitmini/gitrepos/repo2 (push)
mirroring ssh://gitmini@localhost/home/gitmini/gitrepos/repo1 (push)
mirroring ssh://gitmini@localhost/home/gitmini/gitrepos/repo2 (push)
作为下一次尝试我 运行:
$ git config -e
并添加了以下部分:
[remote "mirroring"]
url = ssh://gitmini@localhost/home/gitmini/gitrepos/repo1
fetch = +refs/heads/*:refs/remotes/mirroring/*
pushurl = ssh://gitmini@localhost/home/gitmini/gitrepos/repo1
url = ssh://gitmini@localhost/home/gitmini/gitrepos/repo2
fetch = +refs/heads/*:refs/remotes/mirroring/*
pushurl = ssh://gitmini@localhost/home/gitmini/gitrepos/repo2
但是
$ git remote -vv
mirroring ssh://gitmini@localhost/home/gitmini/gitrepos/repo1 (fetch)
mirroring ssh://gitmini@localhost/home/gitmini/gitrepos/repo1 (push)
mirroring ssh://gitmini@localhost/home/gitmini/gitrepos/repo2 (push)
获取 repo2
的行被忽略了!
事实上,我无法设置配置。我的任务很简单:同步两个遥控器。
编辑:对 torek 给定答案的一些评论:
看来可以设置:
[remote "mirroring"]
url = ssh://gitmini@localhost/home/gitmini/gitrepos/repo1
fetch = +refs/heads/*:refs/remotes/mirroring/*
pushurl = ssh://gitmini@localhost/home/gitmini/gitrepos/repo1
url = ssh://gitmini@localhost/home/gitmini/gitrepos/repo2
fetch = +refs/heads/*:refs/remotes/mirroring/*
pushurl = ssh://gitmini@localhost/home/gitmini/gitrepos/repo2
有了这个配置
$ git push mirroring
...
To ssh://gitmini@localhost/home/gitmini/gitrepos/repo1
...
To ssh://gitmini@localhost/home/gitmini/gitrepos/repo2
结果推送到两个遥控器。
我不知道这个配置是否有效。
托雷克写道:
If you configure more than one, only one of them works, all the others are ignored.
好像不是真的。在我给定的配置中,所有遥控器都将按照我上面的示例通过推拉访问。
事实上,配置为 [remotes]
的组看起来对我的用例非常有用!
远程和获取
Git 可以有很多 "remote",所以当你做 git config -e
时,你会看到这样的东西:
[remote "r1"]
url = ...
fetch = +refs/heads/*:refs/remotes/r1/*
[remote "r2"]
url = ...
fetch = +refs/heads/*:refs/remotes/r2/*
然而,任何一个遥控器只能有一个 url
(最多一个pushurl
)。如果您配置了多个,则只有一个有效,其他的都将被忽略。
(有点奇怪,任何一个遥控器都可以有许多 fetch
条目,并且所有条目都被遵守。此外,您可以在此处设置 push =
以设置默认推送 refspec,尽管我有我自己从来没有用过这个。)
当你 运行 git fetch
你可以命名 一个特定的 远程:
$ git fetch r1
[fetches from r1]
$ git fetch r2
[fetches from r2]
或名称 多个 遥控器使用 --multiple
:
$ git fetch --multiple r1 r2
[fetches from r1 and r2]
或来自所有 遥控器:
$ git fetch --all
[fetches from r1, r2, and any other defined remote]
或来自 "groups",稍后我将对其进行定义。 --multiple
标志使 git fetch
将其所有参数视为远程或组名称。否则,远程名称之后的每个参数都被视为 refspec(例如,git fetch r1 r2
,没有 --all
,意味着从远程 r1
获取 ref r2
)。
A "group" 是定义的东西,例如:
[remotes]
somegroup = r1 r2
您在左侧列出了组,在右侧列出了它表示的一组遥控器。请注意,这是 remotes,复数形式,您可以使用 git config remotes.somegroup r1 r2
设置它,尽管当事情变得如此复杂时,我更喜欢只使用 git config -e
和我的编辑器,这样我就可以一起看到所有的东西了。
使用此集合,您可以 运行 git fetch somegroup
,它将从 r1
和 r2
.
您还可以 运行 git remote update
,默认情况下从您的所有遥控器中获取,但可以配置(通过 remotes.groups
项目以及 remotes.default
)获取来自特定组或单个远程。
推送
使用git push
时,您只能推送到一个远程。要推送到多个遥控器,您必须 运行 几个 git push
es。
(git push --all
并不意味着推送到所有遥控器,而是推送所有参考,就好像您将 refs/*:refs/*
作为参考规范一样。)
Refspecs,或者获取或推送的内容
fetch
和 push
都使用 "refspecs" 来确定他们的工作方式。
完整的 refspec 看起来像您在 remotes 下的 fetch =
行中看到的那些,例如:
+refs/heads/*:refs/remotes/r1/*
有一个可选的前导 +
符号,它设置强制标志(您可以使用 --force
设置相同的标志),然后是两个引用(例如 refs/heads/master
或 refs/tags/v1.1
) 以冒号 :
字符分隔。星号 *
可能会出现,它的工作方式有点像 shell 通配符,只是当它位于 右侧 一侧时,它表示 "use whatever the one on the left side matched"。 (它也不能出现在任意位置;通常你希望它紧跟在 /
之后,如 refs/heads/*
或 refs/*
。)
提取和推送命令不太对称。当做fetch
时,左边的名称或模式是为遥控器的参考,右边的名称是必要的1,因为它告诉git如何重塑本地存储库的名称。这就是为什么远程 origin
的获取行在右边读取 refs/remotes/origin/*
的原因,例如:我们想重新塑造他们所有的 refs/heads/*
引用——他们所有的分支——成为我们的refs/remotes/
中的远程跟踪分支,并放置在 origin/
.
与 git push
但是, 左侧的名称或模式 供您自己参考 - 您的分支、标签、注释或其他任何内容 - 以及名称右边是遥控器。如果省略右侧名称,通常表示 "use the same name on the remote"。因此 refs/heads/master
(没有加号也没有冒号)表示 "push my branch master
to the remote's master
".
(我认为——仅代表我的意见,并非技术要求——最好在定义推送规范的配置文件中使用冒号并在左右两边都明确,即使你可以省略右侧。)
镜像
"Mirroring" 在 git 中有特定的含义,尽管事实证明它有两个不同的含义(fetch
镜像 vs push
镜像)。具体意思就是"set the fetch or pull refspec to copy all references"。例如:
$ git remote add --mirror=fetch foo ssh://foo.foo/foo/foo.git
导致 git 放置:
[remote "foo"]
url = ssh://foo.foo/foo/foo.git
fetch = +refs/*:refs/*
进入配置文件。 (奇怪的是,在这个配置下不会设置 prune = true
。它可能应该设置,但是你可以 运行 git remote update foo --prune
或 git fetch -p foo
来获得相同的效果。)或者:
$ git remote add --mirror=push foo ssh://foo.foo/foo/foo.git
配置:
[remote "foo"]
url = ssh://foo.foo/foo/foo.git
mirror = true
(请参阅 git push
文档)。
请注意,为多个远程设备设置 mirror=fetch 意义不大。例如,假设您为遥控器 r1
和 r2
设置了此项。当您从远程 r1
获取作为获取镜像时,您会清除所有分支和标签,并用来自 r1
的分支和标签替换它们。然后,你从 r2
获取作为获取镜像,清除从 r1
复制的所有分支和标签,用来自 r2
的分支和标签替换它们。 r1
fetch 在这种情况下有什么好处?
1如果您省略右侧,fetch
将无法更新您的任何参考资料。这将是完全无用的,除了有一个历史模式,仍然被 pull
脚本使用,其中获取的引用存放在 FETCH_HEAD
文件中。