2013-06-04 118 views
2

我爲一個項目創建了一個私人git存儲庫,並開發了一個爲每個主要版本創建維護分支的模式發佈。重建一個git承諾有兩個父母,合併多個分支,並保留未來的合併歷史

在項目的幾個月後,我現在有許多老版本的分支,它們不再受任何形式的支持。我意識到,這是一個混亂的方式來處理這個問題。作爲一個更整潔的替代品,我想維護一個開發分支和一個發佈分支,代之以各個版本的標籤。

我理想情況下想將當前存儲庫轉換爲這種新格式。我想盡可能多地保留提交歷史記錄,以發佈提交和主提交之間的關係爲條件,但我希望將所有發佈分支轉換爲一個發佈分支。

desired repository layout - before and after

的倉庫只是由我所用,這樣我就可以一個分支的內容粘貼到另一個分支的末端很容易與git rebase --onto - 我不關心保護的確切承諾哈希這裏。

我擔心的是保存合併歷史與主分支。我想重新提交每個分支的根提交,以便基於前一分支的提示以及最初從主分支提交的提交 - 將其轉換爲合併提交。

然後,我想保留master和那個分支之間的一些其他合併,這發生在鏈條上。

我試圖沿着git rebase --onto branchB-divergence...branchA-tip branchB東西線(和幾個變種,其中包括試圖-m和-i,同時通過文檔拖網)

結果要麼不小心複製了很多的提交上主,並且失去合併歷史,或者不斷髮生需要解決的合併衝突。

我試圖實現甚至可能嗎?我會按照什麼程序來重新提交這樣的一系列提交?

+1

根據您的圖片,還有就是做這個沒有真正的方法,因爲它看起來並不像實際上將分支上的更改合併回'master'。例如:'branch-B'不包含'branch-A'中所做的更改。如果你現在以某種方式使'branch-A'的HEAD成爲'branch-B'第一次提交的父代,那麼你必須將所有從'branch-A'的更改合併到'branch-B'中,從而有效地創建全新的歷史與您實際發佈爲「版本B」的版本無關。 –

+0

啊,這很清楚地解釋了我的幾個合併衝突的問題。在我完全瞭解合併機制之前,在每個分支的頂端發生了一些特定的發佈準備更改。 – Kiirani

回答

1

不要那樣做。爲什麼不爲'LifeSupport'創建一個--orphan分支,它只是一個最後的休息場所,然後將每個死亡分支合併到它上面(合併策略--ours),然後爲每個最後的生命支持提交添加一個標籤適當的版本號。這樣,你可以刪除舊的分支參考,並仍然能夠回到他們的舊版本。

或者使用graftsreplace(Are grafts deprecated?)將舊分支系列加入您指定的鏈中。這些可以通過filter-branch凍結。

+0

嫁接是我想要的。在這裏,有一些聲譽。 – Kiirani

+0

非常感謝。很高興有幫助。 –

2

好的,基於菲利普的回答,我對移植,替換和過濾分支做了一些研究。

因爲我想要實現的是重寫歷史,假裝我正確地放置了我的存儲庫,我決定要實現這個目標的方法是將每個分支的頭部移植到前一個分支,然後運行git filter-branch以使更改永久化。

在新的工作流程,當一個變化完成並準備進入發佈,將被合併到發佈分支。如果您檢查歷史記錄,我希望它看起來像是發生了合併,並得到了有利於任何原始分支頭像的解決方案。

如果在結果看得太仔細,你會發現,其實有沒有合併提交 - 每個嫁接的「合併」可直接通向然後下次提交。這對於我來說並不是什麼大問題,因爲有數十個備用分支在四處漂浮,所以我會讓它無法解決。



嫁接 commit tree with hash labels, before and after grafting

我創建的文件.git/info/grafts。在這個例子中,移植文件中會有兩個條目 - 每個新的分支父條目都有一個條目。

我做了忘記包括提交以及原母公司的第一個錯誤 - 我一半的附件高手消失了,我花了大約過程中注意到的一半。

第二次,我得到了移植文件正確

[commit] [parent] [parent] 
hash2 p2  hash1 
hash4 p3  hash3 



的內容清潔

我結束了與已在早些時候犯下漂浮被刪除了一些未跟蹤文件在我的工作目錄中。我不知道他們是如何結束了那裏的機制,但我知道,他們在我提交歷史會保留下來,所以我剛剛刪除的工作目錄拷貝跑git reset --hard的良好措施。

分支-C是在新版本分支的末端已經指向,所以我只是將其重命名:

% git branch -m branch-C release 

在移植過程中的下一步將是使移植物常駐。 這將需要使用git filter-branch完全重寫提交樹

改寫歷史是好的,對我來說,現在,因爲我只是究竟是誰使用這個倉庫的人。有趣的故事,我正在清理它的主要原因是因爲我打算很快與其他人分享回購協議,而且我不想讓他人頭疼,試圖在其他人依靠穩定後修復佈局歷史。

因爲我會重現那些提交,我不希望老枝指針流連,讓我的老,死棵提交可見。

% git branch -d branch-A 
Deleted branch branch-A (was hash1). 
% git branch -d branch-B 
Deleted branch branch-B (was hash3). 

由於移植,沒有掛提示git抱怨,所以刪除順利。

我還同步存儲庫異地,所以我的跟蹤分支打算留住那些枯樹爲好。這個問題稍後將在push --force上得到解決,但現在,我只是要放棄我的遙控器,以便在我本地仔細檢查我的更改時不會讓我感到困惑。

% git remote remove origin 



改寫歷史

好吧,是時候做不可想象的。我的git倉庫在本地擁有正確的分支佈局,除了發佈和主分支的提示外,沒有指向任何提交的指針。

我已檢出release分支。

沒有參數,git filter-branch將沿着樹走下去,並重寫歷史記錄以使我的所有移植物永久。

% git filter-branch 
Rewrite (...) (73/73) 
Ref 'refs/heads/release' was rewritten 

到目前爲止,我還沒有創建任何那些我在原計劃想閃亮的標籤 - 這是因爲標籤指針會被指向已不存在提交哈希值。

現在我已經檢查了結果,並且我的資源庫看起來是我想要的結果,我將清理嫁接文件並添加這些標記。

.git/info/grafts現在正在移植我不關心的提交,因此,在保密的情況下,我可以完全刪除文件或清除違規項目。

% rm .git/info/grafts 

提交樹仍然看起來是正確的,所以我已經通過並添加了我想要的各種版本的所有標籤。

重寫歷史記錄的最後一步是 - 我想要同步到的遠程存儲庫。

我正在重新添加我的遙控器,這將使我的提交樹看起來都糾纏不清,生病了一段時間。

% git remote add origin (...) 

一開始我嘗試只是在做一個普通git push --force --all,但實際上並沒有刪除已不存在的分支。有一個選項,它被稱爲--prune

% git push --force --all 
Counting objects: 161, done. 
Delta compression using up to 2 threads. 
Compressing objects: 100% (61/61), done. 
Writing objects: 100% (86/86), 9.06 KiB, done. 
Total 86 (delta 48), reused 0 (delta 0) 
To (...) 
* [new branch]  release -> release 

% git push --force --all --prune 
To (....) 
- [deleted]   branch-A 
- [deleted]   branch-B 
- [deleted]   branch-C 

一切都完美,所以我也刪除了備份信息是git的過濾分行發佈分支提出:

% rm .git/refs/original/refs/heads/release 
+0

+1,寫得很好,有很好的軼事。我希望每個人都喜歡你的新回購;-) –