簡體   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