2017-03-24 159 views
7

當您想要重新分配保持合併提交的分支時,您將通過--preserve-merges標誌。當你在git中合併不相關的歷史記錄時,你需要通過--allow-unrelated-histories標誌。允許在git rebase中合併不相關的歷史記錄

如果你正在做git rebase --preserve-merges當現有合併來自一個不相關的歷史,它失敗:

fatal: refusing to merge unrelated histories

如果你嘗試git rebase --preserve-merges --allow-unrelated-histories它失敗:

error: unknown option 'allow-unrelated-histories'

有一些其他的方式來告訴rebase允許合併?


編輯:這裏是一個最小的再現:https://github.com/vossad01/rebase-unrelated-merge-reproduction

要重現結帳master然後執行:

git rebase --preserve-merges --onto origin/a-prime HEAD~2 
+0

你能告訴我們一些關於你想通過合併無關歷史來解決什麼問題的細節嗎? – Schwern

+0

@Schwern我已經將它用於各種各樣的事情,但最近我遇到過的情況是將項目的文檔從GitHub Wiki移動到GitHub Pages(當網站已經存在時)。保留歷史(在這種情況下)的原因是(1)記錄貢獻者和(2)保留修訂歷史。 – vossad01

+0

我無法使用無關的歷史重現您的問題,我的測試回購可能不夠複雜。對於你的情況來說,rebase可能是不合適的,假設一個代碼庫一直在另一個之上開發。他們不是,你確實有平行的發展,如果你保持這種發展,歷史就更有意義。正常合併會更合適,或[子樹合併](https://git-scm.com/book/en/v1/Git-Tools-Subtree-Merging)。 – Schwern

回答

2

蠻力方法是迫使一個共同的根源 - 因爲你」重新嘗試重新綁定根,沒有內容歷史記錄,做一個臨時空提交併告訴git這是您正在合併的歷史記錄的父代:

git rev-list --all --max-parents=0 \ 
| awk '{print $0,empty}' empty=`:|git mktree|xargs git commit-tree` \ 
> .git/info/grafts 
git rebase here 
rm .git/info/grafts 
+0

這讓我的思緒稍微有些了,它起作用了!在笨拙的語言中,它使用[移植](https://git.wiki.kernel.org/index.php/GraftPoint)人爲地使所有分支與空的父/根提交相關。你在Git認爲所有事情都是相關的時候做rebase。然後,你移除移植物以恢復原狀。 – vossad01

2

git rebase合併失敗時,它不會中止rebase,因此您有機會手動干預。

如果您願意手動解決這個問題,你可以完成合並如下:

git merge --allow-unrelated ORIGINAL_BRANCH_THAT_WAS_MERGED --no-commit 
git commit -C ORIGINAL_MERGE_COMMIT 
git rebase --continue 

理想的情況下,也將是Git的處理這種無需人工干預的方式。

0

To reproduce checkout master then execute:

git rebase --preserve-merges --onto origin/a-prime HEAD~2 -i

的混帳底墊文檔說不要合併-i--preserve-merges

[--preserve-merges] uses the --interactive machinery internally, but combining it with the --interactive option explicitly is generally not a good idea unless you know what you are doing (see BUGS below).

但即使沒有它仍然失敗,fatal: refusing to merge unrelated histories-i

部分問題是HEAD~2origin/a-prime的直接祖先。您的測試回購看起來是這樣的:

1 [master] 
| 
2 
|\ 
| | 3 [origin/a-prime] 
| | | 
| 4/[origin/b] 
|/
|/
|/ 
5 [origin/a] 

masterHEAD~2是5 origin/a-prime爲3.你的命令等同於:

git rebase -p --onto 3 5 

5是3的直接祖先,所以該命令沒有按」沒有什麼意義。如果這一切都有效,它會做一些奇怪的事情。


the cases I have encountered a couple of times recently have been in moving a project's documentation from GitHub Wiki to GitHub Pages (when the website already exists).

這是一個不恰當使用底墊。 Rebase將平行的歷史轉化爲線性歷史,基本上假設一組變化一直在另一組之上完成。這對於在功能分支正在處理時保持最新狀態是很好的,如果你沒有一堆中間的合併提交,它們什麼都不做,只是更新分支,那麼簿記和審查就更容易。這些對於閱讀代碼並在未來提交歷史的任何人都是喧囂的。

但是,當你有兩個真正發散的歷史時,最好留下它們作爲發散的歷史。合併它們會告訴我們正確的故事:網站和文檔是分開開發的,但是然後合併成一個單元。

1 - 3 - 5 
     \ 
    2 - 4 - 6 - 7 - 8 [master] 

您可以查看他們分別在拓撲次序(8,7,6,5,3,1,4,2),使用git log --topo-order或可以看看他們交織在日期順序(8,7, 6,5,4,3,2,1),默認爲git log。像gitk或GitX這樣的歷史可視化工具將同時顯示這兩個訂單。我們在網站上工作,然後我們在文檔上工作,然後在某個時間點(你必須找到一個點),出於某種原因,我們工作了一段時間在網站和文件一起。

1 - 3 - 5 - 2 - 4 - 6 - 7 - 8 [master] 

這會失去重要信息,並令人困惑,爲什麼某些變化在未來會變得更加困難。

做一個合併,這是正確的事情。

+0

我同意這兩個存儲庫歷史記錄應該與一個合併。這個問題在合併完成之後就發生了,並沒有試圖對不同的歷史進行線性化(因此'--preserve-merges')。 – vossad01

+0

預期的結果是,2將有父母3和4. – vossad01

+0

@ vossad01對不起,我不關注你的演示回購代表了兩個不相關的分支合併的結果。哪個承諾應該代表兩個不相關的歷史走到一起? 2?合併之前是否存在3個分支?我也不明白你爲什麼在合併之後重新綁定*,試圖完成什麼?您是否試圖將合併之前存在的分支更新爲最新?這是3代表什麼? – Schwern

相關問題