繁体   English   中英

合并复制的存储库中没有真正共同祖先的更改

[英]Merge changes of copied repository without true common ancestor in git

我有一个基于Demo仓库Project1构建的DemoA项目。

不幸的是,DemoA最初只是来自Project1的文件的副本,然后才变成实际的长期项目。 我现在想使Project1成为DemoA的子模块,但是-更重要的是-想将对Project1派生的代码所做的更改合并到DemoA中。

我在DemoA上完成了一个子树拆分,以创建一个分支P1,该分支对DemoA中的Project1代码库进行了所有更改。

在实例化为存储库之前,我还设法添加了对DemoA进行的Project1更改。

Project1
A - B - C - D                     - E
Demo1/P1
    (untracked changes) F - G - H - I

where the files in E are identical to F

我想要的是:

Project 1
A - B - C - D - E - G - H - I

显然,E和F的哈希值是不同的,因此当我将Demo1 / P1添加为Project1的远程对象并尝试合并时,它抱怨没有共同的祖先。

我尝试使用format-patch ,但是git am抱怨

错误:file.xyz:索引中已存在

而我试图基于另一个分支 ,这样做:

git rebase -s recursive -X subtree=project1dir --onto (E-hash) (F-hash) emptybranch

但我显然不了解该操作的实际作用,因为它似乎并没有实际执行任何操作。

有没有一种干净的方法可以做到这一点? 我不介意该过程有些手动性,但我想保留历史。

这都是中等难度的(实际难度级别视情况和您对Git的熟悉程度而异)。

如果文件EF是真正相同的,(或)简单的方法来做到这将是摆在移植(与git replace或移植文件),这样的Git谎称G的母公司承诺是承诺E 也就是说,您具有:

A--B--C--D--E   <-- master

F-------------G--H--I   <-- refs/remotes/rem/P1

git diff master rem/P1~4根本不产生输出( master名称提交Erem/P1~4名称提交F ,并且EF的两棵树完全匹配)。

希望 ,至少作为中间产品,您希望这样做:

A--B--C--D--E   <-- master
             \
F             G--H--I   <-- refs/remotes/rem/P1

就是说,您希望Git假装,至少出于某些目的和一段时间,提交G具有提交E作为其父级。

使用git replace模仿旧的可怕的移植

Git移植程序正是这样做的:它们告诉Git 假装某个提交的父级是其他一些提交。 但是不推荐使用这些方法,而推荐使用更通用的git replace 您可以使用git replace来制作一个类似于G'的新提交G' (但是,至少对于大多数Git命令来说,它是取代的) G ,唯一的区别是G'E为父。

然后,您可以使用git filter-branch重新复制存储库中的提交,以便这种替换成为真实且永久的,而不仅仅是副本。 当然,您将为新的提交获得新的提交哈希( G'可以保留其哈希,但您必须获得新的H'I' )。 请参阅JakubNarębski的回答 ,然后git 嫁接 和替换有何不同? (现在不赞成使用嫁接吗?) ,VonC链接到Jakub的答案。

(Git移植仍然有效,您可以将GE提交的哈希放入.git/info/graftsecho $(git rev-parse rem/P1~3) $(git rev-parse master) > .git/info/grafts ,但是它们一个可怕的骇客,如果您采取了这种技巧,那么最好稍后立即运行过滤器分支(如Jakub所述)。

使用git rebase

您也可以尝试使用git rebase --onto ,但是您必须使用一个指向提交I的现有(普通,本地)分支名称(我不确定emptybranch来源)来启动此rebase。 我认为您可能缺少的步骤可能是使用此常规普通本地分支名称:

git checkout -b rewrite rem/P1

例如,假设名称rem/P1决定提交I git checkout -b rewrite <hash-of-I> ,如果您前面有该哈希表以便于剪切/粘贴。 届时您将拥有:

A--B--C--D--E   <-- master

F-------------G--H--I   <-- HEAD -> rewrite, rem/P1

也就是说,您现在位于这个新的rewrite分支上,该分支指向提交I 现在,您可以git rebase --onto master HEAD~3上,以在当前分支( GHI上复制最近的3次提交。 副本将为G'H'I' ,其中G'的父级为E master点的承诺),而H'的父级为G' ,依此类推:

              G'-H'-I'   <-- HEAD -> rewrite
             /
A--B--C--D--E   <-- master

F-------------G--H--I   <-- rem/P1

现在,由于拥有所需的提交链,因此可以删除远程及其远程跟踪分支。 如果您要的是,您还可以随时快进地master指出要提交I'

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM