共用方式為


瞭解如何從 Subversion (SVN) 遷移至 Git,包括歷程記錄

Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019

從 Subversion (SVN) 等其他版本控制系統移至 Git 時,我們通常建議您執行「提示移轉」,這隻會移轉最新版本的存放庫內容,而不包含歷程記錄。 不過,許多人想要執行更進階的移轉,包括歷程記錄。 本文中提供的指引介紹具有歷程記錄的轉。

SVN 移轉至 Git 可能會因複雜度而異,視存放庫的舊舊程度和已建立和合併的分支數目而定,以及您是否使用一般 SVN 或與 SVK 等相對相對專案而定。

如果:

  • 您有新的存放庫
  • 您有主幹、分支和標記目錄的標準設定

如果:

  • 您的小組已執行許多分支和合併作業
  • 您的存放庫遵循非標準目錄設定
  • 您的目錄設定已隨著時間變更

有數種方式可從 SVN 遷移至 Git。 本文中所述的方法是以使用 Git-svn 為基礎,這是一種 Git 延伸模組,可用來將 Subversion 存放庫簽出至本機 Git 存放庫,然後將變更從本機 Git 存放庫推送回 Subversion 存放庫。 這些步驟提供從 SVN 移轉至 Windows 環境中 Git 的程式詳細概觀,而不需同步處理回原始 SVN 存放庫。 結果將會是一個裸機的 Git 存放庫,可供與小組的其餘人員共用。

注意

在您嘗試將原始程式碼從集中式版本控制系統移轉至 Git 之前,請確定您已熟悉集中式和分散式版本控制系統之間的差異,並 規劃小組的移轉。 準備好之後,您就可以開始移轉。

從 SVN 移轉至 Git 的高階工作流程如下所示:

  • 準備移轉環境
  • 將來源 SVN 存放庫轉換為本機 Git 存放庫
  • (選擇性)同步處理本機 Git 存放庫與 SVN 存放庫的任何變更,而開發人員繼續使用 SVN
  • 將本機 Git 存放庫推送至裝載於 Azure Repos 上的遠端 Git 存放庫
  • 鎖定 SVN 存放庫、將 SVN 存放庫的任何剩餘變更同步至本機 Git 存放庫,並將最終變更推送至 Azure Repos 上的遠端 Git 存放庫
  • 開發人員切換至 Git 作為主要原始檔控制系統

準備移轉環境

在本機工作站上設定移轉環境,並安裝下列軟體:

您也需要為組織建立 Git 存放庫來裝載已轉換的 SVN 存放庫,您可以遵循 在專案中建立新的 Git 存放庫

將來源 SVN 存放庫轉換為本機 Git 存放庫

此步驟的目標是將來源 Subversion 存放庫轉換成本機 裸機 Git 存放庫。 裸機 Git 存放庫沒有可變更之檔案的本機工作簽出,而是只包含存放庫的歷程記錄和存放庫本身的相關元數據。 這是建議的格式,可透過裝載在 Azure Repos 等服務上的遠端存放庫共用 Git 存放庫。

提示

裸機 Git 存放庫的結構不同,並鑒於其沒有工作目錄可防止直接認可存放庫。

裸機 Git 存放庫

擷取所有 Subversion 作者的清單

Subversion 只會針對每個認可使用用戶名稱,而 Git 會同時儲存實名和電子郵件位址。 根據預設,git-svn 工具會在作者和電子郵件欄位中列出 SVN 使用者名稱。 不過,您可以建立 SVN 使用者的對應檔案及其對應的 Git 名稱和電子郵件。

Subversion 使用者

Subversion 使用者

Git 使用者

git 使用者

若要從本機 Subversion 簽出根目錄擷取所有 SVN 使用者的清單,請執行下列 PowerShell 命令:

如需編碼的結果 utf8NoBOM ,請執行下列命令:

svn.exe log --quiet | ? { $_ -notlike '-*' } | % { "{0} = {0} " -f ($_ -split ' | ')[1] } | Select-Object -Unique | Sort-Object | Out-File 'authors-transform.txt' -Encoding utf8NoBOM

如需編碼的結果 ASCII ,請執行下列命令:

svn.exe log --quiet | ? { $_ -notlike '-*' } | % { "{0} = {0} " -f ($_ -split ' | ')[1] } | Select-Object -Unique | Sort-Object | Out-File 'authors-transform.txt' -Encoding ASCII

此命令會擷取所有記錄訊息、擷取使用者名稱、排除任何重複的用戶名稱、排序用戶名稱,並將其放入 UTF-8格式的authors-transform.txt 檔案中(或ASCII 格式,視您指定的編碼方式而定)。 然後,您可以編輯檔案中的每個行,以建立 SVN 用戶的對應至格式正確的 Git 使用者。 例如,您可以對應 jamal = jamal <jamal>jamal = Jamal Hartnett <jamal@fabrikam-fiber.com>

使用 git-svn 複製 Subversion 存放庫

下列命令會使用在先前步驟中建立的 authors-transform.txt 檔案,執行標準 git-svn 轉換。 它會將 Git 存放庫放在 c:\mytempdir 本機電腦的資料夾中。

git svn clone ["SVN repo URL"] --prefix=svn/ --no-metadata --authors-file "authors-transform.txt" --stdlayout c:\mytempdir

注意

--prefix=svn/是必要的,因為否則工具無法從匯入的修訂中判斷 SVN 修訂。 建議您設定前置詞(尾端斜線),因為 SVN 追蹤參考會位於 refs/remotes/$prefix/,這與 Git 自己的遠端追蹤分支配置相容(refs/remotes/$remote/)。

如果您想要追蹤共用通用存放庫的多個項目,設定前置詞也很有用。 根據預設,前置詞會設定為 origin/

如果您使用標準主幹、分支、標記配置,則只會放置 --stdlayout。 不過,如果您有不同的專案,您可能必須傳遞 --trunk--branches--tags 來尋找什麼是內容。 例如,如果您的存放庫結構是 trunk/companydir ,而且您已分支該結構,而不是主幹,您可能會想要 --trunk=trunk/companydir --branches=branches

git svn clone ["SVN repo URL"] --prefix=svn/ --no-metadata --trunk=/trunk --branches=/branches --tags=/tags  --authors-file "authors-transform.txt" c:\mytempdir

注意

此命令可能需要幾分鐘到數小時的時間,視 SVN 存放庫的大小而定。 完成後,您將會有存放庫的 Git 簽出。

轉換版本控制特定組態

如果您的 SVN 存放庫使用 svn:ignore 屬性,您可以使用

cd c:\mytempdir
git svn show-ignore --id=origin/trunk > .gitignore
git add .gitignore
git commit -m 'Convert svn:ignore properties to .gitignore.'

提示

深入瞭解 .gitignore使用 Git 忽略檔案變更

將存放庫推送至裸機 Git 存放庫

在此步驟中,您將建立裸機存放庫,並使其預設分支符合 SVN 的主幹分支名稱。

  1. 建立裸機 Git 存放庫

    git init --bare c:\new-bare.git
    cd c:\new-bare.git
    git symbolic-ref HEAD refs/heads/svn/trunk
    
  2. 將本機 Git 存放庫推送至新的裸機 Git 存放庫

    cd c:\mytempdir 
    git remote add bare c:\new-bare.git 
    git config remote.bare.push refs/remotes/*:refs/heads/* 
    git push bare 
    
  3. trunk 分支重新命名為 main。 您的主要開發分支會命名為「主幹」,其符合它在 Subversion 中的名稱。 您將想要使用下列專案將重新命名為 Git 的標準 main 分支:

    cd c:\new-bare.git
    git branch -m svn/trunk main
    
  4. 清除分支和標記 git-svn 會將所有 Subversion 標籤變成 Git 中非常簡短的分支,格式為 “tags/name”。 您會想要將所有分支轉換成實際的 Git 標籤,或刪除它們。

將 SVN 標籤移至 Git 標籤

cd c:\new-bare.git
git for-each-ref --format='%(refname)' refs/heads/svn/tags | % { $_.Replace('refs/heads/svn/tags/','') } | % { git tag $_ "refs/heads/svn/tags/$_"; git branch -D "svn/tags/$_" }

進階移轉

建立所有 SVN 分支作為適當的 Git 分支

雖然將所有 SVN 分支建立為適當的 Git 分支很容易,但建議您先評估下列幾點,再繼續:

  • 如果有功能分支:您是否可以等到它們整合至主幹后再移轉?

  • 如果有發行分支:讓SVN 保持維護是否有意義? 如果您移轉功能分支,您是否已準備好從 Git 服務分支?

如果您仍想要移轉現有的分支,請執行下列 PowerShell 命令:

git for-each-ref --format='%(refname)' refs/remotes | % { $_.Replace('refs/remotes/','') } | % { git branch "$_" "refs/remotes/$_"; git branch -r -d "$_"; }

注意

此命令可能需要幾分鐘到數小時的時間,視 SVN 存放庫的大小而定。 完成後,您將會有存放庫的 Git 簽出。

僅移轉特定修訂

未指定時, git-svn clone 會將所有修訂從第一個認可 (r1) 移轉至 HEAD。 如果您只需要移轉一組特定的修訂,則 的 git-svn clone 命令應該附加 一個選項。-r

例如,如果您需要從 rev 100 移轉至 HEAD,命令看起來會像這樣:

git svn clone ["SVN repo URL"] --prefix=svn/ --no-metadata --authors-file "authors-transform.txt" --stdlayout c:\mytempdir -r100:HEAD

更新您的工作流程

從集中式版本控制系統移至 Git 不僅僅是移轉程式代碼。 您的小組需要訓練,以瞭解 Git 與現有版本控制系統有何不同,以及這些差異如何影響日常工作。 深入了解

參考資訊

作者:霍薩姆·卡梅爾,威廉·薩拉扎爾 |尋找本文的來源,並與 ALM 連線 |DevOps Rangers 分支指引

(c) 2017 Microsoft公司。 著作權所有,並保留一切權利。 本文件提供「as-is」。本文件中的資訊以及表達的觀點 (包括 URL 及其他網路網站參考) 如有變更,恕不另行通知。 您必須承擔使用本文件的風險。

本文件不提供任何 Microsoft 產品之智慧財產權的法定權利。 您可以複製和使用本文件,以參考為目的供內部使用。