2017-02-21 76 views
2

我有一個存儲庫A(原始存儲庫),它具有完整的提交集。在某個時間點,決定不再使用存儲庫A,並且從頭開始創建新的清理存儲庫B,使用複製+粘貼將所有的存儲庫A的內容(不是將A的內容合併到乾淨的B中,以便保持提交歷史記錄)。我現在想實現的目標是在第三個新的清理存儲庫C中粘貼兩個存儲庫的提交和歷史記錄(歷史記錄是非常重要的)。最終目標是存儲庫C應該包含來自源回收站A和B按時間順序排列,就好像庫B完全沒有創建,例如彷彿工作倉庫A.已進行Git:將兩個存儲庫合併在一起

所以,目前的情況是:

回購答:提交A1>提交A2> A3提交> ...>犯下

回購B:承諾B1 (= A1 + A2 + A3 + ... + An)的>提交B2(=提交的+ 1)> ...>提交BK

嘗試了以下的方法:

git remote add -f A <repo_A_url> 
git merge A/master 
git remote add -f B <repo_B_url> 
git merge B/master 

然後解決的衝突。自從歷史以某種方式搞砸以來,部分工作。

然後嘗試,我認爲最乾淨的方法 - 合併僅回購一成回購C,然後挑櫻桃回購B的提交,從B2 ...... BK。它的工作原理,但櫻桃採摘合併提交減慢了合併過程。

我可以複製一個話題,請告訴我,如果我這樣做,因爲通過爬行通過很多線程,主要看到如何將兩個回購增加到第三個,通過將它們放置在最終回購中的不同文件夾中。如果你可以分享最合適的,符合標準的和可靠的方法。

非常感謝。

回答

0

你可以通過一次提交櫻桃選擇一系列的提交。

$ git merge A/master   # merge A/master into C/master 
$ git cherry-pick B2^..Bk  # cherry-pick all B2 to Bk commits 

或者,你可以rebase。轉到C倉庫master分行。您可以籤一個新的banch(比如說,rebase),那麼合併B /主,重訂其到A/master

$ git checkout -b rebase origin/master # checkout a new branch with clean C-remote/master history 

$ git merge B/master   # merge B/master into C/master 
$ git rebase A/master   # rebase C/master onto A/master 

如果所有的歷史看起來不錯,然後通過rebase分支代替master

$ git checkout rebase   # make sure current branch is rebase 
$ git branch -D master   # delete local master branch 

$ git checkout -b master  # create & checkout a new 'master' branch  
$ git push -f orgin master  # update C-remote/master 
3

如果你的歷史是非常線性的(即只有master在每個A和B),這不會太糟糕。如果有很多分支與之抗衡將獲得更多的參與(見下面的更新),但仍這將提供一個起點:

首先,創建你的C回購。

git clone /url/for/repo/A C 
cd C 

現在的B

git remote add B /url/for/repo/B 
git fetch B 

獲取所有對象現在,我們應該有新的C回購兩種歷史。變基的B回購承諾到史

git rebase --onto master --root B/master 

現在你需要更新master裁判,也許收拾了一下

git branch -f master 
git remote remove B 

現在被列爲你的origin遙控器;你可能要麼推動它,要麼將它作爲一個原點去除,這取決於你是否打算讓A包含前進的一切。

  • UPDATE:好吧,這裏的情況有點更多信息你的歷史不是線性的,因爲它可能永遠不會是......首先,讓我們專注於拓撲結構,然後一兩句話就裁判...

拓撲結構的角度來看,實際上是由三個總體情況:

1)分行和B中合併

因此,讓我們假設你有(如果沒有,通讀這個,但看到情況2),這可以追溯到一個單一的根,你可以移植到A中的單個分支提示(如果沒有看到下面的方案3,則返回到此) 。

A1 ---- A2 ---- A3 <--- (master) 
    \  /
    A4 -- A5 

--------------------------- 

B1 ---- B2 ---- B3 <--- (master) 
    \  /
    B4 -- B5 

在A中可能有分支,但最終他們已經合併回來,您不必擔心它們。在B中也可能有分支,儘管它們被合併回來,但如果rebase試圖使它們成線性,它們可能會造成麻煩。

首先創建C並導入兩個歷史記錄,如上所述。 (最後我會建議這個程序略有變化,與參考文獻無關......但讓我們回到那個。)

現在,你有兩種選擇。最簡單的到目前爲止是使用filter-branch(但它可能很耗時)。找到的提交的哈希值上,你會被移植術(上面注A3)和運行

git filter-branch --parent-filter 'sed "s/^\$/-p xxxxxxxxxx/"' B/master 

(其中XXXXXXXXXX是散列值)。

這的確假設你有sed;它可以在Windows上的git bash環境中使用,也可以在任何* nix系統上使用。如果沒有,你可以拿出一個等效的過濾器。 (它所做的只是說「如果輸入是一個空行,寫出'-p',接着是我正在嫁接的散列;否則將輸入作爲我的輸出」)。

如果對於某些原因你不能這麼做,或者如果它看起來是一個性能問題,那麼你可以嘗試計劃B:給--preserve-merges選項rebase ...這將做你想要的很多時間。 但有一些重要的警告。

基本上如果合併推出手動更改 - 要麼是因爲需要手動解決衝突,或者因爲合併與--no-commit完成,以這種方式引入手動更改 - 然後合併將無法正確通過重訂轉載甚至用這個選項。

在發生衝突的情況下,底墊應該停止,讓你重新申請手冊分辨率(您可能能夠與原有的合併提交的路徑結賬(checkout ... -- .)做的事。但在萬一有人使用--no-commit衍合的甚至不知道什麼是錯的。

如果你知道這將是一個問題,但可以識別一個或兩個問題合併,那麼一種選擇是重訂每個問題合併的父母,然後重做手動合併,然後繼續從那個點開始

如果你不知道if/where p roblems將發生,你可以嘗試rebase然後運行驗證來比較提交。做底墊之前

git checkout master 
git tag old-B-master 

然後嘗試底墊

git rebase --preserve-branches --onto master --root B/master 
git tag new-B-master 

然後做任何驗證的水平似乎是安全給你。 (顯然,以最低的diff的old-B-masternew-B-master。當我做這樣的事情,我寫了一個腳本來遞歸遍歷提交的祖先比較提交的提交。偏執?也許吧。)

除非這正好非常,非常順利,你最好回落到filter-branch的方法。

2)B中

A1 ---- A2 ---- A3 <--- (master) 
    \  /
    A4 -- A5 

--------------------------- 

B1 ---- B2 <--- (master) 
    \ 
    B4 -- B5 <--- (branch1) 

多個分支提示也許您的乙回購未完全合併。這可能會或可能不會使事情複雜化。如果您使用的是filter-branch,它可以同時在多個參考文件上工作。您可能不能只說--all(因爲它可能會捕獲已存在於A樹中的引用,並且操作最終可能會失敗),但是您可以列出B樹中的分支提示。

git filter-branch --parent-filter 'sed "s/^\$/-p xxxxxxxxxx/"' B/master B/branch1 

如果你正在嘗試使用變基(或者,如果你只是想一個尖裁判工作),你可以創建一個臨時章魚合併。

git checkout B/master 
git checkout -b b-entry-point 
git merge -s ours B/branch1 B/branch2 ... 

生成的合併提交是臨時的。 (可以在移植後刪除b-entry-point分支。)它僅在B提交樹中提供了一個「入口點」。

3)在一個

A --- Am <-- (master) 
    \ 
    Ab1 <-- (branch1) 
--------------------------------------- 
B1 ---- B2 <-- (master) 

B3 ---- B4 <-- (branch1) 

多枝梢所以,如果一個並沒有完全擺在首位合併?當你創建回購B時,你是否只有創建單個新提交B === Am?我是這麼猜測的,因爲你不得不做一些奇怪的事情,像多個歷史樹木,以包括Ab1的表示,如果你想重新合併,你稍後會有點頭痛...

如果您確實有多棵樹要移植,那麼我認爲您只需分別處理每棵樹。沒有太多的事情可以改善這一點。

如果您有多個移植分,但他們後來被重新合併爲M所,那麼你可能有單獨移植每個M的父母,然後重新合併爲M',然後繼續嫁接孩子M轉換成M'

好,但對於裁判?

現在上述情況良好,但您可能有(除A和/或B之外)您關心的僅限於master分支的參考。

這是多數民衆贊成由filter-branch更好地處理這些事情之一;事實上,如果我記得正確rebase將不會重寫任何ref,除了分支提示其重定位(甚至不是如果它的遠程分支參考)。

特別是如果使用filter-branch,你可能會發現可以方便地通過克隆B和導入遠程參創建C形成A(而不是周圍的其他方法,如上所示),這樣就可以有filter-branch重寫本地參考文獻爲您。

即便如此,你會發現你需要搬遷遠程裁判的某種組合。可以根據需要使用帶有-f選項的分支和標記命令,將本地參考對齊到最適合您的最終狀態的任何遠程參考。

+0

目前,我正在你的解決方案,它是最好的,現在,我已經之前採用摘櫻桃的方法試過,但正如你所說的,如果有更多的分支機構,將獲得更多的參與和我是什麼在重組期間看到,經常會遇到合併衝突。它們顯然是由於這樣一個事實,即rebase正試圖將B的合併歷史合併到A的頂部來線性化(重新綁定)。如果我不正確,請告訴我。如果是這種情況,是否有可能阻止線性化過程? – Ivan

+0

我會添加一些關於處理多個分支的注意事項;從原來的問題我希望你只是有一個線性的歷史和懶惰。 –

+0

儘管我提供的更新可能會有所幫助,但您可能需要等待第二次更新......我認爲在某些情況下,這些說明會使參考文獻混亂不堪。 –

相關問題