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 存放庫。 這些步驟詳細說明了在 Windows 環境中從 SVN 遷移至 Git 的過程,並且不需要同步回原始的 SVN 存放庫。 結果將會是一個裸的 Git 儲存庫,可與小組其他成員共用。
先決條件
類別 | 需求 |
---|---|
專案存取 | 專案的成員。 |
許可 | - 在私人項目中檢視程式碼:至少 基本 權限。 - 複製或貢獻私人專案中的程式碼:作為 貢獻者 安全群組的成員或在專案中具有相應的許可權。 - 設定分支或存放庫許可權:管理分支或存放庫的許可權 許可權。 - 變更預設分支:編輯原則 存放庫的許可權。 - 匯入存放庫:專案管理員成員 安全組或 Git 專案層級 建立存放庫 許可權設定為 允許。 如需詳細資訊,請參閱 設定 Git 存放庫許可權。 |
服務 | 啟用 Repos。 |
工具 | 選擇性。 使用 az repos 命令:Azure DevOps CLI。 |
注意
在公用專案中,具有 項目關係人 存取權的使用者具有 Azure Repos 的完整存取權,包括檢視、複製及參與程式代碼。
注意
在您嘗試將原始程式碼從集中式版本控制系統移轉至 Git 之前,請確定您已熟悉集中式和分散式版本控制系統之間的差異,並 規劃小組的移轉。 準備好之後,您就可以開始移轉。
從 SVN 移轉至 Git 的高階工作流程如下所示:
- 準備移轉環境
- 將來源 SVN 存放庫轉換為本機 Git 存放庫
- (選擇性)在開發人員繼續使用 SVN 的同時,同步本機 Git 存放庫與 SVN 存放庫的任何變更。
- 將本機 Git 存放庫推送至裝載於 Azure Repos 上的遠端 Git 存放庫
- 鎖定 SVN 存放庫、將 SVN 存放庫的任何剩餘變更同步至本機 Git 存放庫,並將最終變更推送至 Azure Repos 上的遠端 Git 存放庫
- 開發人員切換至 Git 作為主要原始檔控制系統
準備移轉環境
在本機工作站上設定移轉環境,並安裝下列軟體:
- Git
- Subversion
- git-svn 公用程式 (已是 Git 的一部分)
您也需要為組織建立 Git 存放庫來裝載已轉換的 SVN 存放庫,您可以遵循 在專案中建立新的 Git 存放庫
將來源 SVN 存放庫轉換為本機 Git 存放庫
此步驟的目標是將來源 Subversion 存放庫轉換成本機 裸 Git 存放庫。 裸 Git 存放庫沒有可變更檔案的本地工作區,而僅包含存放庫的歷史記錄和有關該存放庫本身的元數據。 這是建議的格式,可透過裝載在 Azure Repos 等服務上的遠端存放庫共用 Git 存放庫。
提示
裸存儲庫 Git 存放庫的結構不同,因為它沒有工作目錄,所以無法直接提交到存放庫。
擷取所有 Subversion 作者的清單
Subversion 只會在每次提交中使用用戶名稱,而 Git 則儲存真實姓名和電子郵件地址。 根據預設,git-svn 工具會在作者和電子郵件欄位中列出 SVN 使用者名稱。 不過,您可以為 SVN 使用者建立一個對應檔案,其中包含相應的 Git 名稱和電子郵件。
Subversion 使用者
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 屬性,您可以藉由以下方式轉換成 .gitignore 文件:
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 的主幹分支名稱。
建立裸 Git 存放庫
git init --bare c:\new-bare.git cd c:\new-bare.git git symbolic-ref HEAD refs/heads/svn/trunk
將本機 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
將
trunk
分支重新命名為main
。 您的主要開發分支將命名為「trunk」,這與它在 Subversion 中的名稱相匹配。 您可能需要使用以下指令將其重新命名為 Git 的標準main
分支:cd c:\new-bare.git git branch -m svn/trunk main
清除分支和標記 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 產品中的智慧財產權的任何法定權利。 您可以複製和使用本文件,以參考為目的供內部使用。