我如何同步两个远程Git存储库? [英] How do I synchronise two remote Git repositories?

查看:112
本文介绍了我如何同步两个远程Git存储库?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个存储库网址,我想同步它们,使它们都包含相同的内容。在Mercurial中,我想要做的是:

  hg pull {repo1} 
hg pull {repo2 }
hg push -f {repo1}
hg push -f {repo2}



<这将在两个回购中产生两个负责人(我知道有两个负责人并不常见,但我这样做是为了同步,并且它需要是非交互式的。负责人将从一个回购站手动合并然后同步再次运行)。



我想在Git中做同样的事情。例如,在没有用户交互的情况下,将所有更改都归入两个回购站,其中有多个分支/头/以后要合并。
我试图在命令中使用urls来做到这一点,而不是添加远程(?),因为可能会涉及大量的回购,并且为它们设置别名将会使我的脚本更加复杂。 / p>

我正在使用 git clone --bar {repo1} 克隆回购,但是我正在努力更新它。我试过 get fetch {repo1} ,但这似乎并没有把我的改变拉下来; git log 仍然没有显示已添加到repo1中的变更集。



我也尝试使用<$我的推送克隆中的c $ c> - mirror ,但似乎从本地不存在的repo2远程变更集,而我需要保留对这两个回收站的更改:/



执行此操作的最佳方法是什么?



编辑:为了让它更清楚我想要做的事情...

我有两个仓库(比如BitBucket和GitHub),并希望人们能够推送到任何一个(最终,一个是Git,一个是Mercurial,但我们假设他们现在都是Git来简化事情)。我需要能够运行一个脚本,以同步两个仓库,这两个仓库都包含两组更改,并且可能需要稍后手动合并。



最终,这意味着我只能与其中一个回购(例如Mercurial)进行交互,并且我的脚本会定期拉入可以合并的Git更改,然后它们将被推回。



在Mercurial中这是微不足道!我只是从两个仓库中取出,并用 -f / - force 来推送,以允许推出多个仓位。然后任何人都可以克隆其中一个回购合并,合并头,并推回。我想知道如何做Git中最接近的类似事情。它必须是100%非交互式的,并且必须保持这两个回购处于可以无限重复处理的状态(这意味着不需要重写历史记录/更改变更集等)。

解决方案

Git分支在Mercurial意义上没有头。只有一件事叫做 HEAD ,它实际上是你目前签出的提交的符号链接。在像GitHub这样的托管版本库中,没有被检出 - 只有版本库历史本身。 (称为裸回购。)



这种差异的原因是Git分支名称完全是任意的;他们不必在存储库的副本之间进行匹配,并且可以随心所欲地创建和销毁它们。[1] Git分支就像Python变量名称一样,可以随意混合并随意使用任何值; Mercurial分支就像C变量,它指向固定的预先分配的内存位置,然后用数据填充。



因此,当您使用Mercurial时,同一分支中有两个历史记录,因为分支名称在这两个存储库中都是固定的有意义的东西。每个历史的叶子是一个头,你通常会合并它们来创建一个头。



但是在Git中,获取远程分支不会实际上影响你的分支。如果您从 origin 获取 master 分支,它将进入名为 origin /主 [2]。 git pull origin master 只是简单的两步操作:将远程分支获取到 origin / master 中,然后合并那个分支插入你当前的分支。但是他们不必有相同的名字;您的分支可以称为开发干线或其他任何东西。您可以将任何其他分支拉入或合并到其中,并且可以将其推送到任何其他分支。 Git并不在乎。



这让我回到你的问题:你不能将第二分支头推到远程Git存储库,因为这个概念不会不存在。您可能会推送到具有重名名称的分支( bitbucket_master ?),但据我所知,您无法更新遥控器的遥控器远程。



但是,我认为你的计划并没有什么意义,因为没有分支的分支机构暴露于这两个存储库,你必须将它们合并,或者你会合并一个,然后将它镜像到另一个之上......在这种情况下,你无缘无故地将第二个存储库置于无用状态。



是否有一个原因,你不能这样做:


  1. 选择一个存储库为规范 - 我假设BitBucket。克隆它。它变成 origin


  2. 将另一个存储库添加为名为 github


  3. 让一个简单脚本定期获取两个远程并尝试合并 github 分支到原点分支。如果合并失败,请中止并向您发送电子邮件或其他内容。如果合并是微不足道的,将结果推送到两个遥控器。


当然,如果你只是做所有的工作在功能分支上,这一切都变得不那么成问题。 :)




[1]它变得更好:您可以合并来自不同存储库的分支,无论历史如何共同点。我已经完成了这项工作来合并分开开始的项目;他们使用不同的目录结构,所以它工作正常。 GitHub对其页面功能使用了类似的技巧:页面的历史存储在一个名为 gh-pages 的分支中,该分支位于同一个存储库中,但完全没有共同的历史记录与您的项目的其余部分。

[2]这是一个白色的谎言。该分支仍然称为 master ,但它属于称为 origin 的远程,并且斜杠是用于引用它。这个区别可能很重要,因为Git没有关于分支名称中斜线的疑问,所以你可以有一个名为 origin / master 的本地分支,这会影响远程分支。 p>

I have two repository urls, and I want to synchronise them such that they both contain the same thing. In Mercurial, what I'm trying to do would be:

hg pull {repo1}
hg pull {repo2}
hg push -f {repo1}
hg push -f {repo2}

This will result in two heads in both repos (I know it's not common to have two heads, but I'm doing this for synchornisation and it needs to be non-interactive. The heads will be merged manually from one of the repos and then the sync run again).

I'd like to do the same thing in Git. Eg., with no user interaction, get all of the changes into both repos, with multiple branches/heads/whatever to be merged later. I'm trying to do this using urls in the commands, rather than adding remotes(?), as there could be a number of repos involved, and having aliases for them all will just make my script more complicated.

I'm currently cloning the repo using git clone --bar {repo1} however I'm struggling to "update" it. I've tried get fetch {repo1} but that doesn't seem to pull my changes down; git log still doesn't show the changeset that has been added in repo1.

I also tried using --mirror in my push and clone, but that seemed to remote changesets from repo2 that didn't exist locally, whereas I need to keep changes from both repos :/

What's the best way to do this?

Edit: To make it a little clearer what I'm trying to do...

I have two repositories (eg. BitBucket and GitHub) and want people to be able to push to either (ultimately, one will be Git, one will be Mercurial, but let's assume they're both Git for now to simplify things). I need to be able to run a script that will "sync" the two repos in a way that they both contain both sets of changes, and may require merging manually later.

Eventually, this means I can just interact with one of the repos (eg. the Mercurial one), and my script will periodically pull in Git changes which I can merge in, and then they'll be pushed back.

In Mercurial this is trivial! I just pull from both repos, and push with -f/--force to allow pushing multiple heads. Then anybody can clone one of the repos, merge the heads, and push back. I want to know how to do the closest similar thing in Git. It must be 100% non-interactive, and must keep both repos in a state that the process can be repeated infinitely (that means no rewriting history/changing changesets etc).

解决方案

Git branches do not have "heads" in the Mercurial sense. There is only one thing called HEAD, and it's effectively a symlink to the commit you currently have checked out. In the case of hosted repositories like GitHub, there is no commit checked out—there's just the repository history itself. (Called a "bare" repo.)

The reason for this difference is that Git branch names are completely arbitrary; they don't have to match between copies of a repository, and you can create and destroy them on a whim.[1] Git branches are like Python variable names, which can be shuffled around and stuck to any value as you like; Mercurial branches are like C variables, which refer to fixed preallocated memory locations you then fill with data.

So when you pull in Mercurial, you have two histories for the same branch, because the branch name is a fixed meaningful thing in both repositories. The leaf of each history is a "head", and you'd normally merge them to create a single head.

But in Git, fetching a remote branch doesn't actually affect your branch at all. If you fetch the master branch from origin, it just goes into a branch called origin/master.[2] git pull origin master is just thin sugar for two steps: fetching the remote branch into origin/master, and then merging that other branch into your current branch. But they don't have to have the same name; your branch could be called development or trunk or whatever else. You can pull or merge any other branch into it, and you can push it to any other branch. Git doesn't care.

Which brings me back to your problem: you can't push a "second" branch head to a remote Git repository, because the concept doesn't exist. You could push to branches with mangled names (bitbucket_master?), but as far as I'm aware, you can't update a remote's remotes remotely.

I don't think your plan makes a lot of sense, though, since with unmerged branches exposed to both repositories, you'd either have to merge them both, or you'd merge one and then mirror it on top of the other... in which case you left the second repository in a useless state for no reason.

Is there a reason you can't just do this:

  1. Pick a repository to be canonical—I assume BitBucket. Clone it. It becomes origin.

  2. Add the other repository as a remote called, say, github.

  3. Have a simple script periodically fetch both remotes and attempt to merge the github branch(es) into the origin branches. If the merge fails, abort and send you an email or whatever. If the merge is trivial, push the result to both remotes.

Of course, if you just do all your work on feature branches, this all becomes much less of a problem. :)


[1] It gets even better: you can merge together branches from different repositories that have no history whatsoever in common. I've done this to consolidate projects that were started separatedly; they used different directory structures, so it works fine. GitHub uses a similar trick for its Pages feature: the history of your Pages is stored in a branch called gh-pages that lives in the same repository but has absolutely no history in common with the rest of your project.

[2] This is a white lie. The branch is still called master, but it belongs to the remote called origin, and the slash is syntax for referring to it. The distinction can matter because Git has no qualms about slashes in branch names, so you could have a local branch named origin/master, and that would shadow the remote branch.

这篇关于我如何同步两个远程Git存储库?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆