簡體   English   中英

如何將具有歷史記錄的 SVN 存儲庫遷移到新的 Git 存儲庫?

[英]How do I migrate an SVN repository with history to a new Git repository?

我閱讀了 Git 手冊、FAQ、Git - SVN 速成課程等,他們都解釋了這個和那個,但你找不到像這樣的簡單說明:

SVN 倉庫在: svn://myserver/path/to/svn/repos

Git 倉庫在: git://myserver/path/to/git/repos

git-do-the-magic-svn-import-with-history \
svn://myserver/path/to/svn/repos \
git://myserver/path/to/git/repos

我不希望它那么簡單,我也不希望它是一個單一的命令。 但我確實希望它不要試圖解釋任何事情——只是說給這個例子采取什么步驟。

創建一個用戶文件(即users.txt )用於將 SVN 用戶映射到 Git:

user1 = First Last Name <email@address.com>
user2 = First Last Name <email@address.com>
...

您可以使用此單行代碼從現有的 SVN 存儲庫構建模板:

svn log -q | awk -F '|' '/^r/ {gsub(/ /, "", $2); sub(" $", "", $2); print $2" = "$2" <"$2">"}' | sort -u > users.txt

如果發現文件中沒有丟失的 SVN 用戶,SVN 將停止。 但在那之后,您可以更新文件並從上次中斷的地方繼續。

現在從存儲庫中提取 SVN 數據:

git svn clone --stdlayout --no-metadata --authors-file=users.txt svn://hostname/path dest_dir-tmp

此命令將在dest_dir-tmp創建一個新的 Git 存儲庫並開始拉取 SVN 存儲庫。 請注意,“--stdlayout”標志意味着您具有常見的“主干/,分支/,標簽/”SVN 布局。 如果您的布局不同,熟悉--tags--branches--trunk選項(一般git svn help )。

允許使用所有常見協議: svn://http://https:// URL 應該針對基本存儲庫,類似於http://svn.mycompany.com/myrepo/repository URL 字符串不得包含/trunk/tag/branches

請注意,執行此命令后,它經常看起來像“掛起/凍結”操作,並且在初始化新存儲庫后它會卡住很長時間是很正常的。 最終,您將看到指示它正在遷移的日志消息。

另請注意,如果您省略--no-metadata標志,Git 會將有關相應 SVN 修訂版的信息附加到提交消息(即git-svn-id: svn://svn.mycompany.com/myrepo/<branchname/trunk>@<RevisionNumber> <Repository UUID> )

如果未找到用戶名,請更新您的users.txt文件,然后:

cd dest_dir-tmp
git svn fetch

如果你有一個大項目,你可能需要多次重復最后一個命令,直到所有的 Subversion 提交都被獲取:

git svn fetch

完成后,Git 會將 SVN trunk檢出到一個新分支。 任何其他分支都設置為遙控器。 您可以使用以下命令查看其他 SVN 分支:

git branch -r

如果您想在您的存儲庫中保留其他遠程分支,您需要手動為每個分支創建一個本地分支。 (跳過主干/主。)如果你不這樣做,分支將不會在最后一步被克隆。

git checkout -b local_branch remote_branch
# It's OK if local_branch and remote_branch are the same name

標簽作為分支導入。 您必須創建一個本地分支,創建一個標簽並刪除該分支以將它們作為 Git 中的標簽。 用標簽“v1”來做到這一點:

git checkout -b tag_v1 remotes/tags/v1
git checkout master
git tag v1 tag_v1
git branch -D tag_v1

將您的 GIT-SVN 存儲庫克隆到一個干凈的 Git 存儲庫中:

git clone dest_dir-tmp dest_dir
rm -rf dest_dir-tmp
cd dest_dir

您之前從遠程分支創建的本地分支只會作為遠程分支復制到新的克隆存儲庫中。 (跳過主干/主。)對於您要保留的每個分支:

git checkout -b local_branch origin/remote_branch

最后,從干凈的 Git 存儲庫中刪除指向現已刪除的臨時存儲庫的遠程:

git remote rm origin

魔法:

$ git svn clone http://svn/repo/here/trunk

Git 和 SVN 的操作非常不同。 你需要學習 Git,如果你想跟蹤 SVN 上游的變化,你需要學習git-svn git-svn主頁有一個很好的例子部分

$ git svn --help

將您的 Subversion 存儲庫干凈地遷移到 Git 存儲庫 首先,您必須創建一個文件,將您的 Subversion 提交作者姓名映射到 Git 提交者,例如~/authors.txt

jmaddox = Jon Maddox <jon@gmail.com>
bigpappa = Brian Biggs <bigpappa@gmail.com>

然后您可以將 Subversion 數據下載到 Git 存儲庫中:

mkdir repo && cd repo
git svn init http://subversion/repo --no-metadata
git config svn.authorsfile ~/authors.txt
git svn fetch

如果您使用的是 Mac,則可以通過安裝git-core +svn從 MacPorts 獲取git-svn git-core +svn

如果您的 subversion 存儲庫與您想要的 git 存儲庫在同一台機器上,那么您可以在 init 步驟中使用此語法,否則都一樣:

git svn init file:///home/user/repoName --no-metadata

我使用了svn2git 腳本,效果很好

我建議在嘗試不斷使用 git-svn 之前先熟悉 Git,即保持 SVN 作為集中存儲庫並在本地使用 Git。

但是,對於具有所有歷史記錄的簡單遷移,這里有幾個簡單的步驟:

初始化本地倉庫:

mkdir project
cd project
git svn init http://svn.url

標記您想要開始導入修訂的時間:

git svn fetch -r42

(或者只是所有轉速的“git svn fetch”)

從那時起實際獲取所有內容:

git svn rebase

您可以使用 Gitk 檢查導入結果。 我不確定這是否適用於 Windows,它適用於 OSX 和 Linux:

gitk

當您在本地克隆了 SVN 存儲庫后,您可能希望將其推送到集中式 Git 存儲庫以便於協作。

首先創建你的空遠程倉庫(可能在GitHub 上?):

git remote add origin git@github.com:user/project-name.git

然后,可選擇同步您的主分支,以便拉操作將自動將遠程 master 與本地 master 合並,當兩者都包含新內容時:

git config branch.master.remote origin
git config branch.master.merge refs/heads/master

之后,您可能有興趣嘗試我自己的git_remote_branch工具,它有助於處理遠程分支:

第一篇解說:《 Git遠程分支

最新版本的后續:“ git 與 git_remote_branch 合作的時間

有一個新的解決方案可以從 Subversion 平滑遷移到 Git(或同時使用兩者): SubGit

我自己在做這個項目。 我們在我們的存儲庫中使用 SubGit - 我的一些隊友使用 Git 和一些 Subversion,到目前為止它運行得非常好。

要使用 SubGit 從 Subversion 遷移到 Git,您需要運行:

$ subgit install svn_repos
...
TRANSLATION SUCCESSFUL 

之后,您將在 svn_repos/.git 中獲得 Git 存儲庫並可以克隆它,或者只是繼續一起使用 Subversion 和這個新的 Git 存儲庫:SubGit 將確保兩者始終保持同步。

如果您的 Subversion 存儲庫包含多個項目,那么將在 svn_repos/git 目錄中創建多個 Git 存儲庫。 要在運行之前自定義翻譯,請執行以下操作:

$ subgit configure svn_repos
$ edit svn_repos/conf/subgit.conf (change mapping, add authors mapping, etc)
$ subgit install svn_repos

使用SubGit,你可以遷移到純 Git(不是 git-svn)並開始使用它,同時只要你需要它仍然保留 Subversion(例如,對於你已經配置的構建工具)。

希望這可以幫助!

請參閱官方git-svn 聯機幫助頁 特別是,在“基本示例”下查看:

跟蹤和貢獻整個 Subversion 管理的項目(包括主干、標簽和分支):

# Clone a repo (like git clone):
    git svn clone http://svn.foo.org/project -T trunk -b branches -t tags

SubGit (與藍屏死機)

subgit import --svn-url url://svn.serv/Bla/Bla  directory/path/Local.git.Repo

這就是全部。

+ 從第一個命令創建的 Git 存儲庫 SVN 更新。

subgit import  directory/path/Local.git.Repo

我使用了一種方法為一個巨大的存儲庫立即遷移到 Git。
當然,你需要一些准備。
但是您可能根本不會停止開發過程。

這是我的方式。

我的解決方案如下:

  • 將 SVN 遷移到 Git 存儲庫
  • 在團隊切換到 .git 之前更新 Git 存儲庫

對於大型 SVN 存儲庫,遷移需要大量時間。
但是更新完成的遷移只需幾秒鍾。

當然,我正在使用SubGit ,媽媽。 git-svn 讓我藍屏死機 只是不斷。 並且 git-svn 對 Git 的“ 文件名太長”致命錯誤感到厭煩。

腳步

1.下載子Git

2.准備遷移和更新命令。

假設我們是為 Windows 做的(移植到 Linux 很簡單)。
在 SubGit 的安裝bin目錄 (subgit-2.XX\\bin) 中,創建兩個 .bat 文件。

用於遷移的文件/命令的內容:

start    subgit import --svn-url url://svn.serv/Bla/Bla  directory/path/Local.git.Repo

“開始”命令在這里是可選的(Windows)。 它將允許在啟動時查看錯誤,並在 SubGit 完成后打開 shell。

您可以在此處添加類似於 git-svn 的其他參數 我只使用--default-domain myCompanyDomain.com來修復 SVN 作者的電子郵件地址的域。
我有標准的 SVN 存儲庫結構(主干/分支/標簽),我們在“作者映射”方面沒有問題。 所以我什么都不做了。

(如果你想遷移像分支這樣的標簽或者你的 SVN 有多個分支/標簽文件夾,你可以考慮使用更詳細的 SubGit 方法

提示 1 :使用 --minimal-revision YourSvnRevNumber 快速查看事情的發展(某種調試)。 特別有用的是查看已解析的作者姓名或電子郵件。
或者限制遷移歷史深度。

提示 2 :遷移可能會被中斷 ( Ctrl + C ) 並通過運行下一個更新命令/文件來恢復。
我不建議對大型存儲庫執行此操作。 我收到了“內存不足 Java+Windows 異常”。

提示 3 :最好創建一個結果裸存儲庫的副本。

用於更新的文件/命令的內容:

start    subgit import  directory/path/Local.git.Repo

當您想要獲取最后一個團隊對您的 Git 存儲庫的提交時,您可以多次運行它。

警告! 不要接觸你的裸倉庫(例如創建分支)。
你會犯下一個致命錯誤:

不可恢復的錯誤:不同步且無法同步...正在將 Subversion 修訂版轉換為 Git 提交...

3.運行第一個命令/文件。 大型存儲庫需要很長時間。 我簡陋的存儲庫需要 30 個小時。

這就是全部。
您可以通過運行第二個文件/命令隨時從 SVN 更新您的 Git 存儲庫。 在您的開發團隊切換到 Git 之前。
只需幾秒鍾。



還有一項更有用的任務。

將本地 Git 存儲庫推送到遠程 Git 存儲庫

是你的情況嗎? 讓我們繼續。

  1. 配置你的遙控器

跑步:

$ git remote add origin url://your/repo.git
  1. 准備將龐大的本地 Git 存儲庫初始發送到遠程存儲庫

默認情況下,您的 Git 不能發送大塊。 致命:遠端意外掛斷

讓我們為它奔跑吧:

git config --global http.postBuffer 1073741824

524288000 - 500 MB 1073741824 - 1 GB 等。

修復您的本地證書問題 如果您的 git-server 使用損壞的證書。

我已禁用證書

此外,您的 Git 服務器可能有需要更正請求數量限制

  1. 將所有遷移推送到團隊的遠程 Git 存儲庫。

使用本地 Git 運行:

git push origin --mirror

git push origin '*:*'對於舊的 Git 版本)

如果您收到以下信息:錯誤:無法生成 git:沒有這樣的文件或目錄......對我來說,我的存儲庫的完整重新創建解決了這個錯誤(30 小時)。 您可以嘗試下一個命令

git push origin --all
git push origin --tags

或者嘗試重新安裝 Git對我沒用)。 或者您可以從所有標簽創建分支並推送它們。 或者,或者,或者……

再生外科醫生

對於復雜的病例, Eric S. Raymond 的reposurgeon 是首選工具。 除了 SVN 之外,它還通過fast-export格式支持許多其他版本控制系統,還支持CVS 作者報告了EmacsFreeBSD等古老存儲庫的成功轉換。

該工具顯然旨在實現近乎完美的轉換(例如將 SVN 的svn:ignore屬性轉換為.gitignore文件),即使對於歷史悠久的困難存儲庫布局也是如此。 在許多情況下,其他工具可能更易於使用。

在深入研究reposurgeon命令行的文檔之前,請務必閱讀出色的DVCS 遷移指南,該指南逐步介紹了轉換過程。

Atlassian 網站上的這份指南是我發現的最好的指南之一:

https://www.atlassian.com/git/migration

這個工具 - https://bitbucket.org/atlassian/svn-migration-scripts - 對於生成authors.txt等也非常有用。

你必須安裝

git
git-svn

從此鏈接復制http://john.albin.net/git/convert-subversion-to-git

1. 檢索所有 Subversion 提交者的列表

Subversion 簡單地列出每個提交的用戶名。 Git 的提交有更豐富的數據,但最簡單的是,提交作者需要列出姓名和電子郵件。 默認情況下,git-svn 工具只會在作者和電子郵件字段中列出 SVN 用戶名。 但是通過一些工作,您可以創建一個包含所有 SVN 用戶以及他們對應的 Git 名稱和電子郵件的列表。 git-svn 可以使用此列表將普通的 svn 用戶名轉換為適當的 Git 提交者。

從本地 Subversion 結帳的根目錄,運行以下命令:

svn log -q | awk -F '|' '/^r/ {sub("^ ", "", $2); sub(" $", "", $2); print $2" = "$2" <"$2">"}' | sort -u > authors-transform.txt

這將抓取所有日志消息,提取用戶名,消除任何重復的用戶名,對用戶名進行排序並將它們放入“authors-transform.txt”文件中。 現在編輯文件中的每一行。 例如,轉換:

jwilkins = jwilkins <jwilkins>

進入這個:

jwilkins = John Albin Wilkins <johnalbin@example.com>

2. 使用 git-svn 克隆 Subversion 存儲庫

git svn clone [SVN repo URL] --no-metadata -A authors-transform.txt --stdlayout ~/temp

這將執行標准的 git-svn 轉換(使用您在第 1 步中創建的 author-transform.txt 文件)並將 git 存儲庫放在主目錄內的“~/temp”文件夾中。

3. 將 svn:ignore 屬性轉換為 .gitignore

如果您的 svn repo 使用 svn:ignore 屬性,您可以使用以下方法輕松將其轉換為 .gitignore 文件:

cd ~/temp
git svn show-ignore > .gitignore
git add .gitignore
git commit -m 'Convert svn:ignore properties to .gitignore.'

4. 推送倉庫到裸git倉庫

首先,創建一個裸倉庫並使其默認分支與 svn 的“trunk”分支名稱匹配。

git init --bare ~/new-bare.git
cd ~/new-bare.git
git symbolic-ref HEAD refs/heads/trunk

然后將臨時存儲庫推送到新的裸存儲庫。

cd ~/temp
git remote add bare ~/new-bare.git
git config remote.bare.push 'refs/remotes/*:refs/heads/*'
git push bare

您現在可以安全地刪除 ~/temp 存儲庫。

5.將“trunk”分支重命名為“master”

您的主要開發分支將被命名為“trunk”,與它在 Subversion 中的名稱相匹配。 您需要使用以下命令將其重命名為 Git 的標准“master”分支:

cd ~/new-bare.git
git branch -m trunk master

6. 清理分支和標簽

git-svn 將所有 Subversions 標簽轉換為 Git 中“標簽/名稱”形式的非常短的分支。 您需要使用以下命令將所有這些分支轉換為實際的 Git 標簽:

cd ~/new-bare.git
git for-each-ref --format='%(refname)' refs/heads/tags |
cut -d / -f 4 |
while read ref
do
  git tag "$ref" "refs/heads/tags/$ref";
  git branch -D "tags/$ref";
done

這一步需要一些打字。 :-) 但是,別擔心; 您的 unix shell 將為以 git for-each-ref 開頭的超長命令提供 > 輔助提示。

GitHub 現在具有從 SVN 存儲庫導入的功能。 不過我從來沒有嘗試過。

僅使用 git、SVN 和 bash 的稍微擴展的答案。 它包括不使用帶有主干/分支/標簽目錄布局的傳統布局的 SVN 存儲庫的步驟(SVN 絕對沒有強制執行這種布局)。

首先使用這個 bash 腳本來掃描你的 SVN 存儲庫中的不同貢獻者並為映射文件生成模板:

#!/usr/bin/env bash
authors=$(svn log -q | grep -e '^r' | awk 'BEGIN { FS = "|" } ; { print $2 }' | sort | uniq)
for author in ${authors}; do
  echo "${author} = NAME <USER@DOMAIN>";
done

使用它來創建一個authors文件,您可以在其中將 svn 用戶名映射到開發人員使用git config屬性user.nameuser.email設置的用戶名和電子郵件(請注意,對於像 GitHub 這樣的服務,只有匹配的電子郵件就足夠了)。

然后讓git svn將 svn 存儲庫克隆到一個 git 存儲庫,告訴它映射:

git svn clone --authors-file=authors --stdlayout svn://example.org/Folder/projectroot

這可能需要非常長的時間,因為 git svn 將單獨檢查存在的每個標簽或分支的每個修訂版。 (注意 SVN 中的標簽只是真正的分支,所以它們最終在 Git 中也是如此)。 您可以通過刪除 SVN 中不需要的舊標簽和分支來加快速度。

在同一網絡中的服務器或同一台服務器上運行它也可以真正加快速度。 此外,如果由於某種原因此過程被中斷,您可以使用

git svn rebase --continue

在很多情況下,您到這里就完成了。 但是如果你的 SVN 倉庫有一個非常規的布局,你在 SVN 中有一個目錄,你想放在一個 git 分支中,你可以做一些額外的步驟。

最簡單的方法是在您的服務器上創建一個新的 SVN 存儲庫,它遵循約定並使用svn copy將您的目錄放在主干或分支中。 如果您的目錄一直位於 repo 的根目錄,這可能是唯一的方法,當我上次嘗試此git svn只是拒絕進行結帳。

您也可以使用 git 執行此操作。 對於git svn clone只需使用您想要放入 git 分支的目錄。

運行后

git branch --set-upstream master git-svn
git svn rebase

請注意,這需要 Git 1.7 或更高版本。

我已經發布了一個分步指南(這里)來將 svn 轉換為 git,包括將 svn 標簽轉換為 git 標簽和將 svn 分支轉換為 git 分支。

精簡版:

1) 從特定版本號克隆 svn。 (修訂號必須是您要遷移的最早版本)

git svn clone --username=yourSvnUsername -T trunk_subdir -t tags_subdir -b branches_subdir -r aRevisionNumber svn_url gitreponame

2)獲取svn數據。 這一步是最耗時的一步。

cd gitreponame
git svn fetch

重復 git svn fetch 直到完成沒有錯誤

3)更新主分支

git svn rebase

4)通過復制引用從svn分支創建本地分支

cp .git/refs/remotes/origin/* .git/refs/heads/

5) 將 svn 標簽轉換為 git 標簽

git for-each-ref refs/remotes/origin/tags | sed 's#^.*\([[:xdigit:]]\{40\}\).*refs/remotes/origin/tags/\(.*\)$#\2 \1#g' | while read p; do git tag -m "tag from svn" $p; done

6) 把倉庫放在更好的地方,比如 github

git remotes add newrepo git@github.com:aUser/aProjectName.git
git push newrepo refs/heads/*
git push --tags newrepo

如果您想了解更多詳細信息,請閱讀我的帖子或問我。

我們可以使用git svn clone命令,如下所示。

  • svn log -q <SVN_URL> | awk -F '|' '/^r/ {sub("^ ", "", $2); sub(" $", "", $2); print $2" = "$2" <"$2">"}' | sort -u > authors.txt

上面的命令將從 SVN 提交創建作者文件。

  • svn log --stop-on-copy <SVN_URL>

當你的 SVN 項目被創建時,上面的命令會給你第一個修訂號。

  • git svn clone -r<SVN_REV_NO>:HEAD --no-minimize-url --stdlayout --no-metadata --authors-file authors.txt <SVN_URL>

上面的命令將在本地創建 Git 存儲庫。

問題是它不會將分支和標簽轉換為推送。 您將不得不手動執行這些操作。 例如下面的分支:

$ git remote add origin https://github.com/pankaj0323/JDProjects.git
$ git branch -a
* master
  remotes/origin/MyDevBranch
  remotes/origin/tags/MyDevBranch-1.0
  remotes/origin/trunk
$$ git checkout -b MyDevBranch origin/MyDevBranch
Branch MyDevBranch set up to track remote branch MyDevBranch from origin.
Switched to a new branch 'MyDevBranch'
$ git branch -a
* MyDevBranch
  master
  remotes/origin/MyDevBranch
  remotes/origin/tags/MyDevBranch-1.0
  remotes/origin/trunk
$

對於標簽:

$git checkout origin/tags/MyDevBranch-1.0
Note: checking out 'origin/tags/MyDevBranch-1.0'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b new_branch_name

HEAD is now at 3041d81... Creating a tag
$ git branch -a
* (detached from origin/tags/MyDevBranch-1.0)
  MyDevBranch
  master
  remotes/origin/MyDevBranch
  remotes/origin/tags/MyDevBranch-1.0
  remotes/origin/trunk
$ git tag -a MyDevBranch-1.0 -m "creating tag"
$git tag
MyDevBranch-1.0
$

現在將 master、branch 和 tags 推送到遠程 git 存儲庫。

$ git push origin master MyDevBranch MyDevBranch-1.0
Counting objects: 14, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (11/11), done.
Writing objects: 100% (14/14), 2.28 KiB | 0 bytes/s, done.
Total 14 (delta 3), reused 0 (delta 0)
To https://github.com/pankaj0323/JDProjects.git
 * [new branch]      master -> master
 * [new branch]      MyDevBranch -> MyDevBranch
 * [new tag]         MyDevBranch-1.0 -> MyDevBranch-1.0
$

svn2git 實用程序

svn2git實用程序刪除了帶有分支和標簽的手動工作。

使用命令sudo gem install svn2git安裝它。 之后運行下面的命令。

  • $ svn2git <SVN_URL> --authors authors.txt --revision <SVN_REV_NO>

現在您可以列出分支、標簽並輕松推送它們。

$ git remote add origin https://github.com/pankaj0323/JDProjects.git
$ git branch -a
  MyDevBranch
* master
  remotes/svn/MyDevBranch
  remotes/svn/trunk
$ git tag
  MyDevBranch-1.0
$ git push origin master MyDevBranch MyDevBranch-1.0

想象一下你有 20 個分支和標簽,顯然 svn2git 會為你節省很多時間,這就是為什么我比原生命令更喜歡它。 它是原生git svn clone命令的一個很好的包裝器。

有關完整示例,請參閱我的博客條目

TortoiseGit 就是這樣做的。 看到這篇博文: http : //jimmykeen.net/articles/03-nov-2012/how-migrate-from-svn-to-git-windows-using-tortoise-clients

是的,我知道用鏈接回答不是很好,但這是一個解決方案,嗯?

對於GitLab用戶,我在此處提供了有關如何從 SVN 遷移的要點:

https://gist.github.com/leftclickben/322b7a3042cbe97ed2af

從 SVN 遷移到 GitLab 的步驟

設置

  • SVN 托管在svn.domain.com.au
  • SVN 可以通過http訪問(其他協議應該可以工作)。
  • GitLab 托管在git.domain.com.au並且:
    • 使用命名空間dev-team創建一個組。
    • 至少創建了一個用戶帳戶並將其添加到組中,並具有用於遷移的帳戶的 SSH 密鑰(使用ssh git@git.domain.com.au測試)。
    • 項目favourite-projectdev-team命名空間中創建。
  • 文件users.txt包含相關用戶詳細信息,每行一個用戶,格式為username = First Last <address@domain.com.au> ,其中username是 SVN 日志中給出的用戶名。 (有關詳細信息,請參閱參考資料部分中的第一個鏈接,特別是用戶 Casey 的回答)。

版本

  • 顛覆版本 1.6.17 (r1128011)
  • git 版本 1.9.1
  • GitLab 版本 7.2.1 ff1633f
  • Ubuntu 服務器 14.04

命令

bash
git svn clone --stdlayout --no-metadata -A users.txt 
http://svn.domain.com.au/svn/repository/favourite-project
cd favourite-project
git remote add gitlab git@git.domain.com.au:dev-team/favourite-project.git
git push --set-upstream gitlab master

而已! 在 GitLab Web UI 中重新加載項目頁面,您將看到現在列出的所有提交和文件。

筆記

  • 如果有未知用戶, git svn clone命令將停止,在這種情況下,更新users.txtcd favourite-projectgit svn fetch將從停止的地方繼續。
  • SVN 存儲庫的標准trunk - tags - branches布局是必需的。
  • 提供給git svn clone命令的 SVN URL 停止在trunk/tags/branches/之上的級別。
  • git svn clone命令產生大量輸出,包括頂部的一些警告; 我忽略了警告。

如果您使用 SourceTree,則可以直接從應用程序執行此操作。 轉到 File -> New/Clone 然后執行以下操作:

  1. 輸入遠程 SVN URL 作為“源路徑/URL”。
  2. 出現提示時輸入您的憑據。
  3. 輸入本地文件夾位置作為“目標路徑”。
  4. 給它一個名字。
  5. 在高級選項中,從“創建本地存儲庫類型”的下拉列表中選擇“Git”。
  6. 您可以選擇指定要從中克隆的修訂。
  7. 點擊克隆。

在 SourceTree 中打開 repo,您​​將看到您的提交消息也已遷移。

現在轉到 Repository -> Repository Settings 並添加新的遠程 repo 詳細信息。 如果您願意,請刪除 SVN 遠程(我通過“編輯配置文件”選項完成此操作。

當您准備好並自由編碼時,將代碼推送到新的遠程存儲庫。

我強烈推薦我剛剛發現的這個簡短的截屏系列 作者帶您了解基本操作,並展示一些更高級的用法。

另一方面,當嘗試使用 git-svn dcommits 進行 git 時,git-stash 命令是天賜之物。

一個典型的過程:

  1. 設置 git 倉庫
  2. 對不同的文件做一些工作
  3. 決定使用 git 檢查一些工作
  4. 決定svn-dcommit
  5. 得到可怕的“無法使用臟索引提交”錯誤。

解決方案(需要 git 1.5.3+):

git stash; git svn dcommit ; git stash apply

這是一個沒有依賴項的簡單 shell 腳本,它將一個或多個 SVN 存儲庫轉換為 git 並將它們推送到 GitHub。

https://gist.github.com/NathanSweet/7327535

在大約 30 行腳本中:使用 git SVN 克隆,從 SVN::ignore 屬性創建一個 .gitignore 文件,推送到裸 git 存儲庫,將 SVN 主干重命名為 master,將 SVN 標簽轉換為 git 標簽,並將其推送到 GitHub同時保留標簽。

將十幾個 SVN 存儲庫從 Google Code 遷移到 GitHub,我經歷了很多痛苦。 我使用 Windows 並沒有幫助。 Ruby 在我的舊 Debian 機器上被各種損壞,讓它在 Windows 上運行是個笑話。 其他解決方案無法與 Cygwin 路徑一起使用。 即使我開始工作了,我也無法弄清楚如何讓標簽顯示在 GitHub 上(秘訣是 --follow-tags)。

最后,我拼湊了兩個簡短的腳本,鏈接在上面,效果很好。 解決方案不需要比這更復雜!

我在 Windows 機器上做了一個小批量,只需調用即可將具有歷史記錄(但沒有分支)的 SVN 存儲庫傳輸到 GIT 存儲庫

transfer.bat http://svn.my.address/svn/myrepo/trunk https://git.my.address/orga/myrepo

也許任何人都可以使用它。 它創建了一個 TMP 文件夾,用 git 檢出那里的 SVN 存儲庫,並添加新的源並推送它......並再次刪除該文件夾。

@echo off 
SET FROM=%1 
SET TO=%2 
SET TMP=tmp_%random%

echo from:  %FROM% 
echo to:    %TO% 
echo tmp:   %TMP%

pause

git svn clone  --no-metadata --authors-file=users.txt %FROM% %TMP%  
cd %TMP% 
git remote add origin %TO% 
git push --set-upstream origin master


cd .. 
echo delete %TMP% ... 
pause

rmdir /s /q %TMP%

您仍然需要帶有用戶映射的 users.txt,例如

User1 = User One <u.1@xxx.com>

我只是想為 Git 社區添加我的貢獻。 我編寫了一個簡單的 bash 腳本來自動執行完全導入。 與其他遷移工具不同,此工具依賴於原生 git 而不是 jGit。 此工具還支持具有大修訂歷史和/或大 blob 的存儲庫。 它可以通過 github 獲得:

https://github.com/onepremise/SGMS

此腳本將使用以下格式轉換存儲在 SVN 中的項目:

/trunk
  /Project1
  /Project2
/branches
     /Project1
     /Project2
/tags
 /Project1
 /Project2

這個方案也很受歡迎並得到支持:

/Project1
     /trunk
     /branches
     /tags
/Project2
     /trunk
     /branches
     /tags

每個項目將按項目名稱同步:

Ex: ./migration https://svnurl.com/basepath project1

如果您希望轉換完整的 repo,請使用以下語法:

Ex: ./migration https://svnurl.com/basepath .

首先,歸功於@cmcginty 的回答。 這對我來說是一個很好的起點,我在這里發布的大部分內容都大量借鑒了它。 然而,我正在移動的存儲庫有多年的歷史,這導致了在回復這封信之后出現的一些問題(數百個分支和標簽需要手動移動一個;稍后閱讀更多)。

因此,經過數小時的搜索和反復試驗,我能夠編寫一個腳本,使我能夠輕松地將多個項目從 SVN 移動到 GIT,並且我決定在這里分享我的發現,以防其他人站在我的立場上。

<tl;dr> 讓我們開始吧


首先,創建一個“Authors”文件,它將基本的 svn 用戶轉換為更復雜的 git 用戶。 最簡單的方法是使用命令從您要移動的 svn 存儲庫中提取所有用戶。

svn log -q | awk -F '|' '/^r/ {sub("^ ", "", $2); sub(" $", "", $2); print $2" = "$2" <"$2">"}' | sort -u > authors-transform.txt

這將生成一個名為authors-transform.txt 的文件,其中為每個在運行它的svn repo 中進行更改的用戶對應一行。

someuser = someuser <someuser>

更新以包含 git 的全名和電子郵件

someuser = Some User <someuser@somewhere.com>

現在使用您的作者文件開始克隆

git svn clone --stdlayout --no-metadata -r854:HEAD --authors-file=authors-transform.txt https://somesvnserver/somerepo/ temp
  • --stdlayout 表示 svn repo 遵循標准的 /trunk /branches /tags 布局
  • --no-metadata 告訴 git 不要在每次 git 提交時標記與 svn 提交相關的元數據。 如果這不是單向轉換,請刪除此標簽
  • -r854:HEAD 僅從修訂版 854 開始獲取歷史記錄。 這是我遇到第一個障礙的地方; 我正在轉換的 repo 在修訂版 853 中有一個“損壞”的提交,因此它不會克隆。 使用此參數允許您僅克隆部分歷史記錄。
  • temp 是將創建以初始化新 git repo 的目錄的名稱

這一步可能需要一段時間,特別是在大型或舊的 repo 上(我們的一個大約需要 18 小時)。 您還可以使用該 -r 開關僅獲取一小段歷史記錄來查看克隆,然后再獲取其余部分。

移動到新目錄

cd temp

如果您只在克隆中提取部分內容,則獲取任何丟失的歷史記錄

git svn fetch

標記在克隆期間創建為分支。 如果您只有幾個,您可以一次轉換它們。

git 1.0.0 origin/tags/1.0.0

但是,如果您有數百個標簽,這會很乏味,因此以下腳本對我有用。

for brname in `git branch -r | grep tags | awk '{gsub(/^[^\/]+\//,"",$1); print $1}'`; do echo $brname; tname=${brname:5}; echo $tname; git tag $tname origin/tags/$tname; done

您還需要結帳要保留的所有分支

git checkout -b branchname origin/branches/branchname

如果你也有很多分支,這個腳本可能會有所幫助

for brname in `git branch -r | grep -v master | grep -v HEAD | grep -v trunk | grep -v tags | awk '{gsub(/^[^\/]+\//,"",$1); print $1}'`; do echo $brname; git checkout -b $brname origin/$brname; done

這將忽略主干分支,因為它已經作為 master 檢出並保存一個步驟,稍后刪除重復的分支,並忽略我們已經轉換的 /tags。

現在是查看新存儲庫的好時機,並確保您有一個本地分支或標記您想要保留的任何內容,因為稍后將刪除遠程分支。

好的,現在讓我們將我們檢出的所有內容克隆到一個干凈的倉庫(此處命名為 temp2)

cd ..
git clone temp temp2
cd temp2

現在我們需要再檢查一次所有的分支,然后再將它們推送到最終的遙控器,所以按照上面你最喜歡的方法。

如果您關注 gitflow,您可以重命名您的工作分支以進行開發。

git checkout -b WORKING
git branch -m develop
git push origin --delete WORKING
git push origin -u develop

現在,如果一切正常,您就可以推送到您的 git 存儲庫了

git remote set-url origin https://somebitbucketserver/somerepo.git
git push -u origin --all
git push origin --tags

我確實遇到了最后一個問題,即 Control Freak 最初阻止我推送不是我創建的標簽,因此如果您的團隊使用 Control Freak,您可能需要禁用或調整該設置以進行初始推送。

下載適用於 Windows 的 Ruby 安裝程序並使用它安裝最新版本。 將 Ruby 可執行文件添加到您的路徑中。

  • 安裝 svn2git
  • 開始菜單 -> 所有程序 -> Ruby -> 使用 Ruby 啟動命令提示符
  • 然后輸入“gem install svn2git”並輸入

    遷移 Subversion 存儲庫

  • 打開 Ruby 命令提示符並轉到要遷移文件的目錄

    然后svn2git http://[域名]/svn/ [repository root]

  • 將項目遷移到 Git 可能需要幾個小時,具體取決於項目代碼大小。

  • 這個主要步驟有助於創建如下所述的 Git 存儲庫結構。

    SVN(/Project_components)主干--> Git master SVN(/Project_components)分支--> Git分支SVN(/Project_components)標簽--> Git標簽

創建遠程存儲庫並推送更改。

GitHub 有一個導入器。 創建存儲庫后,您可以通過其 URL 從現有存儲庫導入。 如果適用,它會詢問您的憑據,然后從那里開始。

當它運行時,它會找到作者,你可以簡單地將他們映射到 GitHub 上的用戶。

我現在已經將它用於一些存儲庫,而且它非常准確而且速度也快得多! 一個有大約 4000 次提交的存儲庫花了 10 分鍾,然后我的朋友花了四天時間!

這里的幾個答案參考https://github.com/nirvdrum/svn2git ,但對於大型存儲庫,這可能會很慢。 我嘗試使用https://github.com/svn-all-fast-export/svn2git代替它是一個名稱完全相同但用於將 KDE 從 SVN 遷移到 Git 的工具。

設置它需要做更多的工作,但是當我完成轉換時,它本身就花了幾分鍾,而另一個腳本則花費了幾個小時。

有不同的方法來實現這個目標。 我已經嘗試了其中的一些,發現只有在 Windows 操作系統上安裝了 git 和 svn 才能真正工作。

先決條件:

  1. Windows 上的 git(我用過這個) https://git-scm.com/
  2. 安裝了控制台工具的 svn(我使用了 tortoise svn)
  3. 轉儲 SVN 存儲庫的文件。 svnadmin dump /path/to/repository > repo_name.svn_dump

實現最終目標的步驟(將所有具有歷史記錄的存儲庫移動到 git,首先是本地 git,然后是遠程)

  1. 在目錄 REPO_NAME_FOLDER cd REPO_NAME_PARENT_FOLDER創建空存儲庫(使用控制台工具或 tortoiseSVN),將 dumpfile.dump 放入 REPO_NAME_PARENT_FOLDER

  2. svnadmin load REPO_NAME_FOLDER < dumpfile.dump等待這個操作,可能要很久

  3. 這個命令是靜默的,所以打開第二個 cmd 窗口: svnserve -d -R --root REPO_NAME_FOLDER為什么不直接使用 file:///...... ? 由於答案https://stackoverflow.com/a/6300968/4953065 ,下一個命令將失敗並顯示Unable to open ... to URL:

  4. 創建新文件夾 SOURCE_GIT_FOLDER

  5. cd SOURCE_GIT_FOLDER
  6. git svn clone svn://localhost/ 等待這個操作。

最后,我們得到了什么?

讓我們檢查我們的本地存儲庫:

git log

看到你之前的提交了嗎? 如果是 - 好的

因此,現在您擁有功能齊全的本地 git 存儲庫,其中包含您的源代碼和舊的 svn 歷史記錄。 現在,如果要將其移動到某個服務器,請使用以下命令:

git remote add origin https://fullurlpathtoyourrepo/reponame.git
git push -u origin --all # pushes up the repo and its refs for the first time
git push -u origin --tags # pushes up any tags

就我而言,我不需要標簽命令,因為我的倉庫沒有標簽。

祝你好運!

將svn子模塊/文件夾'MyModule'轉換為具有歷史記錄的git,沒有標簽或分支。

要保留svn忽略列表,請在步驟1之后使用以上注釋

有效地將 Git 與 Subversion 結合使用是對 git-svn 的溫和介紹。 對於現有的 SVN 存儲庫,git-svn 使這變得非常簡單。 如果您要開始一個新的存儲庫,首先創建一個空的 SVN 存儲庫然后使用 git-svn 導入要容易得多,而不是相反。 創建一個新的 Git 存儲庫,然后導入到 SVN 中是可以完成的,但這有點痛苦,尤其是如果您是 Git 新手並希望保留提交歷史記錄。

我使用以下腳本讀取包含我所有 SVN 存儲庫列表的文本文件並將它們轉換為 Git,然后使用git clone --bare轉換為裸 Git 存儲庫:

#!/bin/bash
file="list.txt"
while IFS= read -r repo_name
do
 printf '%s\n' "$repo_name"
 sudo git svn clone --shared --preserve-empty-dirs --authors-file=users.txt file:///programs/svn/$repo_name
 sudo git clone --bare /programs/git/$repo_name $repo_name.git
 sudo chown -R www-data:www-data $repo_name.git
 sudo rm -rf $repo_name
done <"$file"

list.txt 的格式為:

repo1_name
repo2_name

並且 users.txt 具有以下格式:

(no author) = Prince Rogers <prince.rogers.nelson@payesley.park.org>

www-data 是 Apache Web 服務器用戶,需要權限才能通過 HTTP 推送更改。

多合一 - 用於SVNGIT遷移的 shell 腳本。 使用占位符<>提及GITSVN詳細信息

#!/bin/bash

######## Project name 
PROJECT_NAME="Helloworld"
EMAIL="example mail"

#Credientials Repo
GIT_USER='<git username>'
GIT_PWD='<git password>'
SVN_USER='<svn username>'
SVN_PWD='<svn password>'

######## SVN repository to be migrated # Dont use https - error will be thrown
BASE_SVN="<SVN URL>/Helloworld"

#Organization inside BASE_SVN
BRANCHES="branches"
TAGS="tags"
TRUNK="trunk"

#Credientials
git config --global user.name '<git username>'
git config --global user.password '<git password>'
git config --global credential.helper 'cache --timeout=3600'

######## GIT repository to migrate - Ensure already project created in Git
GIT_URL=https://$GIT_USER:$GIT_PWD@<GIT URL>/Helloworld.git

###########################
#### Don't need to change from here
###########################

#Geral Configuration
ABSOLUTE_PATH=$(pwd)
TMP=$ABSOLUTE_PATH/$PROJECT_NAME

#Branchs Configuration
SVN_BRANCHES=$BASE_SVN/$BRANCHES
SVN_TAGS=$BASE_SVN/$TAGS
SVN_TRUNK=$BASE_SVN/$TRUNK

AUTHORS=$PROJECT_NAME"-authors.txt"

echo '[LOG] Starting migration of '$SVN_TRUNK
echo '[LOG] Using: '$(git --version)
echo '[LOG] Using: '$(svn --version | grep svn,)

mkdir $TMP
echo
echo '[DIR] cd' $TMP
cd $TMP

echo
echo '[LOG] Getting authors'
svn --username $SVN_USER --password $SVN_PWD log -q $BASE_SVN | awk -F '|' '/^r/ {sub("^ ", "", $2); sub(" $", "", $2); print $2" = "$2" <"$2"@"$EMAIL">"}' | sort -u >> $AUTHORS

echo
echo '[RUN] git svn clone --authors-file='$AUTHORS' --trunk='$TRUNK' --branches='$BRANCHES' --tags='$TAGS $BASE_SVN $TMP
git svn clone --authors-file=$AUTHORS --trunk=$TRUNK --branches=$BRANCHES --tags=$TAGS $BASE_SVN $TMP

#Not working so no need to mention it
#--stdlayout $PROJECT_NAME
echo
echo '[RUN] svn ls '$SVN_BRANCHES
svn ls $SVN_BRANCHES

echo 
echo 'git branch -a'
git branch -a

echo
echo '[LOG] Getting first revision'
FIRST_REVISION=$( svn log -r 1:HEAD --limit 1 $BASE_SVN | awk -F '|' '/^r/ {sub("^ ", "", $1); sub(" $", "", $1); print $1}' )

echo
echo '[RUN] git svn fetch -'$FIRST_REVISION':HEAD'
git svn fetch -$FIRST_REVISION:HEAD

#Branches and Tags  
echo
echo '[RUN] svn ls '$SVN_BRANCHES
for BRANCH in $(svn ls $SVN_BRANCHES); do
    echo git branch ${BRANCH%/} remotes/svn/${BRANCH%/}
    git branch ${BRANCH%/} remotes/svn/${BRANCH%/}
done

git for-each-ref --format="%(refname:short) %(objectname)" refs/remotes/origin/tags | grep -v "@" | cut -d / -f 3- |
while read ref
do
  echo git tag -a $ref -m 'import tag from svn'
  git tag -a $ref -m 'import tag from svn'
done

git for-each-ref --format="%(refname:short)" refs/remotes/origin/tags | cut -d / -f 1- |
while read ref
do
  git branch -rd $ref
done
  
echo
echo 'git tag'
git tag

echo
echo 'git show-ref --tags'
git show-ref --tags

echo
echo '[RUN] git remote add origin '$GIT_URL
git remote add origin $GIT_URL

echo
echo '[RUN] git push'
git push origin --all --force
git push origin --tags

#echo git branch -d -r trunk
#git branch -d -r trunk

git config --global credential.helper cache
echo 'Successful.'
  • 當您運行上面的腳本時,它將從 SVN 獲取分支和標簽詳細信息並將其放在.git文件夾下。
  • 交叉檢查SVN中的所有分支是否都應在此.git/refs/heads文件夾下可用。
  • 如果在SVN中缺少某些分支,則手動將分支文件從.git/refs/remotes/origin/<branches>復制到.git/refs/heads
  • 只復制分支(包括master )並忽略任何tagstrunk
  • 現在再次運行腳本。 您可以在 git 存儲庫中看到所有branchestags

為此,我通過以下過程使用了svn2git庫:

sudo apt-get install git-core git-svn ruby
須藤寶石安裝 svn2git
svn 日志 --quiet | grep -E "r[0-9]+ \\| .+ \\|" | 剪切 -d'|' -f2 | sed 's/ //g' | 排序 | uniq >authors.txt(此命令用於映射作者)

以上步驟應在您要從 svn 轉換為 git 的文件夾中執行。

像這樣在authors.txt中每行添加一個映射

anand = Anand Tripathi <email_id>
trip = Tripathi Anand <email_id>

為新的 git 存儲庫創建一個文件夾並執行下面的命令,路徑為authors.txt

svn2git <svn_repo_path> --nobranches --notags --notrunk --no-minimize-url --username <user_name> --verbose  --authors <author.txt_path>

If no trunk and no tag and branch is present then have to execute the above command else if root is trunk then mention rootistrunk or trunk is present then --trunk <trunk_name>

git遠程添加原點
git push --all 原點
git push --tags 原點

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM