2017-05-19 86 views
0

我有一個在svn存儲庫中有超過3年曆史的項目。它被遷移到git,但是做這個的人,只是拿最後一個版本,拋棄所有這3年的歷史。更改根提交父指向另一個提交(連接兩個獨立的git存儲庫)

現在項目在一個存儲庫中有最近3-4個月的歷史記錄,並且我已經將其他3年的svn歷史記錄導入到新的git存儲庫中。

是否有某種方法將第二個存儲庫的根提交連接到第一個提交的最後一個提交?

它是這樣的:

* 2017-04-21 - last commit on master 
    | 
    * 2017-03-20 - merge branch Y into master 
    |\ 
    | * 2017-03-19 - commit on branch Y 
    | | 
    * | 2017-03-18 - merge branch X into master 
/| * 2017-02-17 - commit on another new branch Y 
* |/ 2017-02-16 - commit on branch X 
| * 2017-02-15 - commit on master branch 
* | 2017-01-14 - commit on new branch X 
\| 
    * 2017-01-13 - first commit on new repository 
    | 
    * 2017-01-12 - init new git project with the last version of the code in svn repository 
    . 
    . 
There is no relationship between the two different repositories yet, this is what I wanna 
do. I want to connect the root commit of 2nd repository with the last commit of the first 
one. 
    . 
    . 
    * 2017-01-09 - commit 
    | 
    * 2017-01-08 - commit 
    | 
    * 2017-01-07 - merge 
/| 
* | 2016-01-06 - 2nd commit the other branch 
| * 2016-01-05 - commit on trunk 
* | 2016-01-04 - commit on new branch 
\| 
    * 2015-01-03 - first commit 
    | 
    * 2015-01-02 - beggining of the project 

更新:

我剛剛得知,我需要做一個git rebase,但如何?請讓我們考慮提交日期,例如它是SHA-1代碼...答案是使用git filter-branch--parent-filter選項,而不是git rebase

更新2:

我試着命令git filter-branch --parent-filter 'test $GIT_COMMIT = 443aec8880e898710796a1c4fb4decea1ca5ff66 && echo "-p 98e2b95e07b84ad1e40c3231e66840ea910e9d66" || cat' HEAD並沒有奏效:

PS D:\git\rebase-test\rep2cc> git filter-branch --parent-filter 'test $GIT_COMMIT = 443aec8880e898710796a1c4fb4decea1ca5ff66 && echo "-p 98e2b95e07b84ad1e40c3231e66840ea910e9d66" || cat' HEAD 
fatal: ambiguous argument '98e2b95e07b84ad1e40c3231e66840ea910e9d66 || cat': unknown revision or path not in the working tree. 
Use '--' to separate paths from revisions, like this: 
'git <command> [<revision>...] -- [<file>...]' 

更新3:

它沒有在Windows CMD工作或PowerShell,但它確實在Git Bash上運行。

+2

那麼,你有沒有考慮過在同一個存儲庫中取得這兩個數據,然後在另一個數據庫上重新規劃一個歷史?這當然會重寫所有提交歷史的提交。 –

+1

Lasse說得對。只要建立一個新的回購與svn克隆正確,添加一個遠程這個搗毀回購,獲取和櫻桃選擇正確克隆svn回購史上克隆從svn後完成的git。 – eftshift0

+0

我是新的git,我剛剛得知我正在尋找的魔術字是'rebase' – lmcarreiro

回答

2

首先要做的事情是:您需要一個具有所有可用歷史記錄的回購單。

用最近的歷史製作回購克隆。將舊歷史記錄添加爲遠程回購。我建議這個克隆是一個「鏡像」,你用這個替換你的原始回購。但是,您也可以將--mirror關閉,然後您可以通過推送(可能強制推送,具體取決於您使用哪種方式)完成返回原點。

git clone --mirror url/of/current/repo 
cd repo 
git remote add history url/of/historical/repo 
git fetch history 

你需要做的下一件事是找出你將拼接歷史的地方。描述這個術語有點模糊,我想...你想要的是找到兩個提交對應於最近的SVN修訂,這兩個歷史都有一個提交。例如您的SVN回購含有1版本,2,3和4。現在你有

Recent-History Repo 

C --- D --- E --- F <--(master) 

Old-History Repo 

A --- B --- C' --- D' 

其中A代表第1版,B代表第2版,CC'代表版本3,和DD'表示版本4. EF是在原始遷移後創建的工作。因此,您想要將父項爲D(本例中爲E)的提交拼接到D'

現在,我可以想到兩種方法,每種方法都有優缺點。

改寫近代史

IMO的最佳方式如果你能協調各開發商切到一個新的回購(意思是你安排的時候,他們都同意,所有未完成的工作所以他們放棄他們的克隆;然後你做了轉換;然後他們都重新克隆)是(有效地)將最近的歷史重新放到舊的歷史上。

如果真的只是一個分支,那麼你可以從字面上使用衍合

git rebase --onto D' D master 

(其中DD'與提交的SHA ID替換)。

更有可能你有一些分支機構,並在最近的歷史合併;在這種情況下,重組操作將很快開始成爲問題。另一方面,您可以利用DD'具有相同的樹的事實 - 因此rebase和re-parent或多或少是等價的。

因此,您可以使用git filter-branch--parent-filter來進行重寫。根據在https://git-scm.com/docs/git-filter-branch在文檔中的例子,你會做這樣的事情

git filter-branch --parent-filter 'test $GIT_COMMIT = D && echo "-p D'" || cat' HEAD 

(其中再次DD'與提交的SHA ID替換)。

這會創建您需要清理的「備份」參考。最後,你會得到

A --- B --- C' --- D' --- E' --- F' <--(master) 

這是一個事實,即F是由F'它創造了一個硬割接(或多或少)需要更換。

現在,如果您在第1步創建了鏡像克隆,則可以考慮擦除引用日誌,放棄遠程設備並運行gc,然後這是一個新的即用型源代碼回購。

如果你製作了一個常規克隆,那麼你需要push -f所有的參考來源,這可能會在原點回購中留下一些混亂。

使用「替代提交」

其他選項不創建一個硬割接,但它留給你的小麻煩來處理,直到永遠。您可以使用git replace。在您的合併回購

git replace `D` `D'` 

默認狀態下,產生的日誌輸出或任何時候,如果發現的git D,它會在輸出替代D'(和它的歷史)。

有一些已知的故障。可能有未知的故障。默認情況下,使這一切工作的「替代參考」不共享,所以你必須有意識地推送和獲取它們。

+0

我試過git替換,它不是我想要的。而且我的歷史上有很多分支機構和合並,所以,轉換操作確實成了一個問題,就像你說的。 – lmcarreiro

+0

第三種選擇,我不明白......什麼是「P」和「P」?並且命令'git filter-branch --parent-filter'test $ GIT_COMMIT = D && echo「-p D'」||貓'頭'會在Windows上工作嗎? – lmcarreiro

+0

對不起,「P」和「P」應該和其他地方一樣是「D」和「D」我已更新。該命令將在'git bash'外殼的窗口中工作;只記得用適當的提交引用(例如SHA ID)替換'D'和'D'' –

相關問題