Git

將多個 svn 儲存庫遷移到單個 git 儲存庫

  • August 24, 2012

我們希望從 svn 永久遷移到 git,以便能夠在分支和協作方面使用 git 的更好功能。

我們目前的 svn 儲存庫看起來像這樣

svnrepo/
  frontend/
     trunk
     branches/
        ng/
        ...
     tags/
        1.x
        ...
  backend/
     trunk
     branches/
        ng/
        ...
     tags/
        1.x
        ...

工作佈局是我們簽出前端項目,並在其中創建一個後端文件夾並簽出後端項目。

我們現在想遷移到 git,並放棄前端和後端之間的分離(就作為單獨的項目而言),因為它給我們帶來的問題多於優勢。我們希望它們都在一個 git 儲存庫中。

我想使用svn2git進行轉換。不幸的是,最新的開發都發生在一個分支中,而不是在主幹中,但我認為這對 svn2git 來說應該不是問題。所以新的 git 儲存庫佈局應該是這樣的:

/            => svnrepo/frontend/branches/ng
/backend     => svnrepo/backend/branches/ng

其中 => 表示“遷移/轉換自”。

對於轉換,我們不需要將 svn 儲存庫中的所有標籤和分支轉換為 git。這對我們來說並不重要。然而重要的是,我們擁有對分支/ng 目錄中所有文件的所有送出的完整歷史記錄,從主幹返回分支以及之前在主幹中發生的所有送出。我們希望所有這些送出都在單個 git 儲存庫中使用上述佈局。這甚至可能嗎?我們將如何做到這一點?

我已經在 google 和 stackoverflow 12中進行了搜尋,但找不到針對我們問題的確切解決方案。

一種解決方案是使用 svn2git 或僅使用 svn2git 單獨生成每個儲存庫git svn(這是一個已經內置在 git 中的不錯的小工具),然後將它們與git filter-branch.

  1. 單獨複製每個 svn 儲存庫。
  2. 在您想成為 root 的儲存庫中,將其他儲存庫添加為遠端,並獲取您想要合併到該儲存庫的分支(您會收到警告,因為分支沒有共同的歷史記錄;這是預期的)。
  3. 在這些新分支上執行git filter-branch,使用索引過濾器為它們生成一個新的子目錄。
  4. 將過濾後的分支合併到master根儲存庫上(或您想要的任何分支)。完整的歷史將被保留。

第 3 步的命令如下所示:

git filter-branch --index-filter '
   git ls-files -s |
   perl -pe "s{\t\"?}{$&newsubdir/}" |
   GIT_INDEX_FILE=$GIT_INDEX_FILE.new git update-index --index-info &&
   mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE
' HEAD

魔術,每次我必須這樣做時,它確實感覺有點像魔術,就是perl聲明。在每次送出時git filter-branch過濾索引,並在所有 blob 路徑(即更改工作樹的文件路徑)之前添加“newsubdir”。您可能必須四處試驗才能使路徑完全正確。從以前走過這條路的人那裡學到的一些教訓:

  • 備份一切。 git filter-branch是破壞歷史的。一旦你改變它,你就不能輕易地把它改回來。請務必備份您正在使用的所有儲存庫副本。沒有什麼比完成一項複雜的操作並發現您錯過了/路徑更糟糕的了。
  • **編寫所有內容。**除非你有一些嚴肅的技能;你不會第一次就做到這一點。在完成每個步驟時編寫腳本,以便輕鬆重新執行其中任何一個步驟。此外,如果您在一周後發現自己搞砸了一面旗幟,您可以立即複製。
  • 在 EC2 中的集群計算實例上花費 20 美元。 git filter-branch佔用大量 CPU 資源。對深度歷史的索引過濾器可能需要數小時才能在您的本地環境中執行,但在 AWS集群計算實例上只需要一小部分時間。當然,它們每小時花費 2 美元多一點,但你只需要幾個小時。免去您的痛苦,並使用您在硬體上編寫的那些腳本,使操作變得微不足道。它花費了一頓美味午餐的價格。

引用自:https://serverfault.com/questions/420828