0xC*_*22L 9 git mercurial github hg-git mercurial-extension
我有一个项目,其主要(Mercurial)存储库位于SourceForge上,但Bitbucket(Mercurial)和Github(Git)上有克隆.
现在我一直在使用hg-git将Mercurial存储库推送到Github,根据我对该过程的理解,一些元数据在过程中保存在Mercurial存储库中.
现在,当重新克隆Bitbucket存储库并重新克隆Github存储库时,如果我发出一个hg pull ../github-repo
我得到:
pulling from ../github-repo
searching for changes
abort: repository is unrelated
Run Code Online (Sandbox Code Playgroud)
为什么这样,我怎么能说服Mercurial确实他们有关系呢?或者我是否必须依赖我最初推送到Github的原始存储库?我仍然有,但假设我失去了它,我有什么选择,缺少手动变更集移植?
注意:由于拉取请求,Github仓库已更改(新变更集).但SourceForge和Bitbucket repos仍然认为彼此是相关的.现在的任务是将变换集从Github Git repo拉到本地,并分别将它们推回到SourceForge和Bitbucket.
Liv*_*ius 10
相关或非相关位基本上来自两个存储库是否共享公共根,即初始变更集.
为了强迫拉力,你可以用移植物或移植物延伸物做一些邪恶的事情,但这可能会产生连锁反应,你似乎对这种解决方案不利 - 我也会这样做!
要了解你遇到问题的原因,你需要了解一下Hg-Git的工作原理.
真正的问题是Hg-Git基本上是动态创建一个新的repo.因此,两个存储库的相关原因与产品无关hg convert some-existing-hg-repo
与原始存储库无关.到目前为止,您还没有注意到它,因为Hg-Git也在另一个方向上执行此操作 - 当您从Mercurial存储库启动时,它会创建必要的Git存储库.当您第一次开始克隆到GitHub时,您在其服务器上创建了一个裸Git存储库,其所有意图和目的都与每个存储库相关.因此,你推动由Hg-Git创建的新Git仓库是相关的,一切正常,没问题.之后,你正在推动同样的回购,所以再没有问题 - Hg-Git跟踪当地Git和Hg存储库之间的关系,从而保持了你们的关系.但是当你重新开始时,你会创建一个新的Git和/或Hg仓库(取决于你要进入的方向)并且通信被打破.
Hg-Git的工作原理是创建一个隐藏的Git存储库,并建立Git和Hg存储库的提交之间的对应关系.Hg-Git是一个双向桥,也就是说,它能够进行Git提交并生成Hg提交,反之亦然.Hg-Git通过使用Python编写的git-library(dulwich)并将Mercurial作为扩展链接来实现双语.这意味着Hg-Git在不需要git
安装二进制/ Git参考实现的情况下读取和写入Git存储库.但是,Hg-Git是一个Mercurial扩展,因此依赖于Mercurial的Mercurial结束以及用户界面.这就是为什么要努力创建反向接口(Git-Hg等)以便Git用户可以使用Git与Mercurial进行交互.
现在,是否创建了Git或Hg存储库取决于首先如何创建混合存储库.由于你来自规范的Mercurial方面,我们将从那里开始.
当您在Github或Bitbucket上创建存储库时,它最初是裸的并且没有提交,因此与每个存储库相关 - 这是默认情况下创建存储库时没有初始提交的动机的一部分.(对于Git和Mercurial都是如此.)存储库相关性基于根节点.因此,任何存储库都可以推送到这个新的存储库.当你跑步hg push ssh+git://git@github.com/user/some-git-repo
Hg-Git第一次在您的本地文件夹中创建一个新的,隐藏的Git存储库,然后使用Git协议进行通信并将更改推送到远程.从那时起,您应该在两个存储库之间进行通信时没有问题 - 从根节点的初始转换和父子关系,可以实现两个存储库的更改集之间的一对一映射.(这不是100%真实,特别是如果你使用Git或Mercurial的更高级的惯用功能,但它现在就足够了.)Hg-Git追踪的信息比这更多,我很确定如果没有其他原因,只能通过连续的推拉来加快速度.那么,当你从Mercurial克隆开始时,你的"原始根"
现在,如果您不是从本地Mercurial克隆开始,而是从远程Git克隆开始,那么您实际上最终会从Git克隆创建一个Mercurial克隆 - "proto-root"是Git根.更确切地说,当你运行时hg clone ssh+git://git@github.com/user/some-git-repo
,Mercurial启动,检查以确保它可以与远程接口(它可以通过Hg-Git的帮助),然后创建目录并调用必要的扩展名,即Hg-Git.Hg-Git然后.git
在你的.hg
文件夹中创建一个隐藏文件夹,执行一个git clone,然后将Git repo转换为Mercurial; 一旦克隆完成,它就会调用hg update
,直接在Mercurial仓库上运行,而不必了解Git仓库.
我怀疑,这是你的情况出了什么问题.当您从GitHub执行新的克隆时,实际上您创建了一个新的Mercurial存储库,当然与您的原始存储库无关 - 就像产品与原始存储库无关的情况一样hg convert
,即使变异提交不包括初始提交.(这有点像你将某些东西翻译成另一种语言然后再回来时,你并不总是得到原始形式.)出于各种原因,我怀疑Hg-Git以与时间无关且确定的方式执行转换(几乎肯定是后者,但它可能会添加关于转换本身的额外元数据,这意味着不是前者).如果是这种情况,那么您应该能够从规范的Hg克隆开始并重新创建与Git存储库的连接.(是的,初始转换的方向性有所不同有些问题,但最好与开发人员讨论设计决策的优缺点.)
回到混合Hg-Git存储库的结构.这里有两个有趣的事情:
重要的是,您实际上可以通过系统Git直接在隐藏的Git存储库上运行.如果您使用Hg-Git,那么Git存储库仅在推送到远程Git克隆时拉动,这意味着那些本地直接Git更改将与Mercurial存储库不同步 - 在最坏的情况下,您提交几次到Git,然后提交Mercurial而不同步并有效地创建两个单独的分支,因为Hg提交和Git提交共享一个共同的祖先但不相互构建.但是,Hg-Git提供了一种手动强制repos via hg gimport [git-repo-to-import-from-if-not-local-hidden]
和之间同步的机制hg gexport
(默认情况下导出为本地隐藏副本,如果需要,可以创建它).强制执行此同步还应该为您提供处理您注意到的问题的方法.您可以使用Git来拉(或者在Git术语中,fetch
- git pull
相当于hg pull --update
; git fetch
是hg pull
,这使得Mercurial fetch扩展名称真的很不幸)将新的更改集放入Git存储库,然后用于hg gimport
将这些更改集导入Mercurial存储库.
现在,如果您执行了编辑历史记录等操作,那么所有投注都会被取消.我不确定Hg-Git会如何处理这个问题 - 我怀疑它最终会创造出双打.Mercurial克隆中的新提交将添加到Git中,但删除的更改集仍在Git仓库中,可能会导回到Mercurial存储库中.(这是Hg-Git离线同步变更集方法的直接结果.)在这种情况下,我建议选择一个规范的存储库,擦除所有克隆并对所有克隆被这个混乱无效的人道歉.(顺便说一句,这是Mercurial社区对编辑历史非常谨慎的部分原因.)
@EmilSit建议您hg pull git+ssh://github.com/you/githubrepo.git
直接从规范(非GitHub克隆)Mercurial存储库运行.假设Hg-Git创建初始Git克隆的方法完全与时间无关且具有确定性,那么这有一个很好的工作机会.(后者几乎可以肯定,但我不确定前者,请参阅上面的文字以获取更多细节.)
你可以做这个的本地变体:git clone ssh://github.com/you/githubrepo.git
用来获取一个本地纯git克隆,然后做hg pull ../githubrepo
.(这需要你安装了Git.)Hg-Git应该自动启动并进行转换.转换还取决于Hg-Git以确定的,与时间无关的方式进行转换.
您可以直接在原始混合存储库中的隐藏git存储库上操作.使用git fetch
(您可能首先必须先cd
进入.git
隐藏在.hg
文件夹中的文件夹).然后运行hg gimport && hg update
以从git存储库导入更改并更新.(您可能已指定路径gimport
- 或者.
是隐藏的git repo的路径.我怀疑您也可以指定GitHub路径.)
您可以使用各种哑转移方法 - 导出补丁系列等 - 并手动提交它们.如果您想在进行手动提交时给予其他开发人员信用,那么您可以使用该-u
选项在每次提交的基础上设置用户.
您可以使用移植物或移植扩展进行智能移植.首先,使用Hg-Git来执行GitHub存储库的新Mercurial克隆.然后使用其中一个扩展来将两个Mercurial存储库组合在一起.
至少有一种非移植方法应该有效,因为除非Hg-Git按时间依赖它,否则应该可以找到一个共同的根.即使找到了一个共同的根,你也可能会找到两个基本上重复的(未命名的)分支,然后你必须将它们合并在一起.