[英]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.