如果你的歷史是非常線性的(即只有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-master
對new-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
選項的分支和標記命令,將本地參考對齊到最適合您的最終狀態的任何遠程參考。
目前,我正在你的解決方案,它是最好的,現在,我已經之前採用摘櫻桃的方法試過,但正如你所說的,如果有更多的分支機構,將獲得更多的參與和我是什麼在重組期間看到,經常會遇到合併衝突。它們顯然是由於這樣一個事實,即rebase正試圖將B的合併歷史合併到A的頂部來線性化(重新綁定)。如果我不正確,請告訴我。如果是這種情況,是否有可能阻止線性化過程? – Ivan
我會添加一些關於處理多個分支的注意事項;從原來的問題我希望你只是有一個線性的歷史和懶惰。 –
儘管我提供的更新可能會有所幫助,但您可能需要等待第二次更新......我認爲在某些情況下,這些說明會使參考文獻混亂不堪。 –