[英]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的熟悉程度而异)。
如果文件E
和F
是真正相同的,(或)简单的方法来做到这将是摆在移植(与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
名称提交E
, rem/P1~4
名称提交F
,并且E
和F
的两棵树完全匹配)。
您希望 ,至少作为中间产品,您希望这样做:
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移植仍然有效,您可以将G
和E
提交的哈希放入.git/info/grafts
: echo $(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
上,以在当前分支( G
, H
和I
上复制最近的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.