我希望有多个远程服务器,它们应该为所有分支互相镜像。
开始这次冒险,我发现: 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
,但这也会导致错误配置的结果。
如某些评论所述,如果重复命令,可以添加网址。但我永远不能添加一个以上的回购。作为例子,我可以去看看这个结果,对我来说这似乎充满了错误:
$ 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
导致推动两个遥控器。
我不知道这个配置是否有效。
Torek写道:
如果您配置了多个,只有其中一个可以使用,其他所有都会被忽略。
似乎不是真的。在我给定的配置中,所有遥控器都将通过推拉来访问,如上面的示例所示。
事实上,使用[remotes]
配置的组看起来对我的用例非常有用!
答案 0 :(得分:2)
Git可以有很多&#34;远程&#34; s,所以当你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 =
设置来设置默认的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]
或来自&#34;群组&#34;,我将在稍后定义。 --multiple
标志使git fetch
将其所有参数视为远程或组名。否则,远程名称后的每个参数都被视为refspec(例如,git fetch r1 r2
,而不是--all
,意味着从远程r2
获取引用r1
。
A&#34; group&#34;是用例如:
定义的东西[remotes]
somegroup = r1 r2
在左侧列出组,在右侧列出遥控器组。请注意,这是远程 s ,复数,您可以使用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/*
作为refspec一样。)
fetch
和push
都使用&#34; refspecs&#34;确定如何开展工作。
完整的refspec看起来就像你在遥控器下的fetch =
行中看到的那样,例如:
+refs/heads/*:refs/remotes/r1/*
有一个可选的前导+
符号,用于设置强制标记(可以使用--force
设置相同的标记),然后是两个引用(例如refs/heads/master
或{{1 }}由冒号refs/tags/v1.1
字符分隔。可能会出现一个星号:
,它有点像shell globbing,除了它在 right 一侧时,它意味着&#34;使用左边的那个方匹配&#34;。 (它也不能出现在任意位置;通常你想在*
之后,/
或refs/heads/*
。
fetch和push命令不是完全对称的。在执行refs/*
时,左侧的名称或模式用于远程的引用,右侧的名称是必要的 1 ,因为它告诉git如何重新确定本地存储库的名称。这就是远程fetch
的获取行在右侧读取origin
的原因,例如:我们想要重新塑造所有refs/remotes/origin/*
引用 - 所有分支 - 成为我们的远程跟踪refs/heads/*
中的分支,并置于refs/remotes/
下。
但是,对于origin/
,左侧上的名称或模式是您自己的引用 - 您的分支,标签,备注或其他 - 以及上的名称对适用于遥控器。如果省略右侧名称,通常意味着&#34;在遥控器上使用相同的名称&#34;。因此,git push
(无加号且无冒号)表示&#34;将我的分支refs/heads/master
推送到远程master
&#34;。
(我认为 - 我的意见 - 不是技术要求 - 它是最好的,在定义refspecs推送的配置文件中,你使用冒号并明确左右两侧,即使你可以省略右侧。)
&#34;镜像&#34;在git中有一个特定的含义,虽然事实证明它有两个不同的含义(master
镜像与fetch
镜像)。具体含义只是简单地设置fetch或pull refspec来复制所有引用&#34;。例如:
push
导致git放置:
$ git remote add --mirror=fetch foo ssh://foo.foo/foo/foo.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
文档)。
请注意,对多个遥控器进行mirror = fetch是没有意义的。例如,假设您为遥控器git push
和r1
设置了此项。当您从远程r2
作为提取镜像提取时,您将清除所有分支和标记,并使用r1
中的分支和标记替换它们。然后,您从r1
作为提取镜像进行提取,清除从r2
复制的所有分支和标记,并使用r1
中的分支和标记替换它们。在这种情况下r2
fetch做了什么好事?
1 如果省略右侧,r1
根本无法更新任何参考文献。这将是完全无用的,除了fetch
脚本仍然使用的历史模式,其中获取的引用存储在pull
文件中。