Alan Tsai 的學習筆記


學而不思則罔,思而不學則殆,不思不學則“網貸” 記錄軟體開發的點點滴滴 著重於微軟技術、網頁開發、DevOps、C#, Asp .net Mvc、Azure、AI、Chatbot、Docker、Data Science

[git]開始使用git - 用git操作svn repo

2017-06-25 Sunday
git

git作為分散式版控的一項優勢是可以在offline的情況下查到log,並且能夠隨時隨地commit;這個對於當中央repo在公司內部的時候會更加有感(因為通常內部都要透過vpn,就有可能導致速度慢,甚至有些vnp還會切斷你的外網, 沒有google要怎麼寫code XD)

很不幸的,如果你今天被要求使用svn或者tfs,你就沒有辦法像git一樣在無連線狀態下查log。

但是別絕望,git其實可以透過一個Bridge來和svn溝通,從外部來看,你好像還是使用svn,但是其實你實際上使用git。所以git的那些優點(local有一個版本,因此可以local commit,快速切branch等)完全可以使用。

這是一個很好開始嘗試git的方式。

題外話,我當初接觸git就是為了他的local功能,因為實在太好用了,最後慢慢就希望全部換成git。

昨天有幸為 Study4的6月場次介紹git,其中有學員有特別提到關於git和svn溝通的部分, 因此把當初所做的事情作了一些整理。如果有任何地方看不懂或者有缺或者漏的地方,在留言給我。

這篇的情境

這篇的主要的情境是:作為一個開發者,我的中央版控使用的是svn,但是我希望使用git來管控應該怎麼做?

因此,這是一個單項同步的概念:svn中央庫作為main repo,而不是說在建立一個中央的git repo然後和中央svn做雙向同步

這篇針對的是windows環境,在linux和mac不確定是否一樣操作,但是本質應該差不多。

用git作為svn的溝通需要準備什麼?

首先有幾個程式是必備的:

Git for windows

既然要用git做為和svn溝通的工具,git當然是需要安裝的程式。

快速鏈接:Git for windows

git svn
這個是git和svn溝通的bridge - 以前需要額外下載,目前是整合在git for windows裡面
svn的command line工具

如果有安裝TortoiseSVN(小烏龜),可以不用安裝,小烏龜有帶。

可以再CollabNet下載到,目前最新版本是1.9.5

快速鏈接:(x86)、(x64)

非必備程式:

svn-migration-scripts.jar

這個是Atlassian提供的一個小工具,方便處理一些事情。如果要使用也需要安裝java

source位置:source

快速鏈接:直接下載

如果不確定是否所需要的工具都有了,可以用 svn-migration-scripts.jar做檢查,在command line輸入:

java -jar svn-migration-scripts.jar verify

執行完的結果,列出幾個工具使用的版本
執行完的結果,列出幾個工具使用的版本

準備工作 - svn使用者對照表

在svn裡面,誰commit是用帳號做表現,但是在git裡面則是 姓名+email。

很有可能目前svn和git的對應著無法直接對上,因此先建立一個對應表。

這個對應表的格式很簡單,就是:

{{svn帳號}} = {{git姓名}} <{{git email}}>

多人,就是每個人空一行。

以我的例子來說,假設svn帳號是J00,然後要對到我,那麼這個檔案內容就會是:

J00 = Alan Tsai <alan@alantsai.net>

使用工具產生

假設你的人名清單很明確可以一個一個自己手刻,但是如果很多情況下建議用產生的方式。

產生有兩種方式:

  1. 用svn-migration-scripts.jar
  2. 用svn log搭配一些工具產生 - 需要先用svn把repo抓下來,個人覺得比較麻煩

用svn-migration-scripts.jar

執行 (把 {{svn repo url}} 換成對應的repo url):

java -jar svn-migration-scripts.jar authors {{svn repo url}} > author.txt

會得到這個repo裡面每一個使用者的清單,在手動調整一下對應的git名稱即可,下面是我拿open source的一個svn repo的產生結果:

某個open source svn的人名清單,這邊沒有pipe到檔案因此可以直接看到
某個open source svn的人名清單,這邊沒有pipe到檔案因此可以直接看到

用svn log產生

這個的前期條件是已經有把那個svn repo用svn抓下來。

在那個資料夾下面執行:

svn log --quiet --xml | sed -n -e "s/<\/\?author>//g" -e "/[<>]/!p" | sort | sed "$!N; /^\(.*\)\n\1$/!P; D" > author.txt

這個會得到一個所有svn使用者的清單。

請注意建立出來的txt檔案格式,一定要是UTF-8 (不包含BOM)

這個可以用Visual Studio Code看出來,在右下角,UTF-8是對的。假設要改,可以點一下,然後選擇Save with Encoding在選擇UTF-8即可。

看到編碼,UTF-8 with BOM是錯的選擇save with encoding選擇 UTF-8
選擇為UTF-8

開始使用 git svn

整個的使用流程如下:

  1. 從svn建立git repo
  2. 日常git版控行為 (開branch,commit,merge master等) 這個就不說明
  3. 從svn抓取最新
  4. 把git的commit推上svn

從svn建立git repo

首先是需要把svn所有commit抓下來,這個如果svn repo很大的話,需要一些時間,因此要做好放著讓他跑的準備。

如果你的svn repo是標準方式建立的(換句話說,會有trunk、branches和tags的話)呼叫方式如下:

git svn clone svn://localhost svn -A author.txt --stdlayout --prefix=svn/

參數說明如下:

-A
這個傳入的是那個帳號名稱對應檔 - 在 準備工作 - svn使用者對照表 篇的到的結果檔案
--stdlayout
表示svn使用的是標準方式建立出來,如果今天不是標準方式建立,那麼需要自己設定 trunk名稱: --trunk=,branch名稱:--branches=和 tag名稱:--tags=
--prefix=svn/
建立出來的svn 遠端 branch用 svn/作為前戳,方便區分哪些是svn那邊的remote branch。
git svn clone其實就是:
git svn int
   git svn fetch
的縮寫
假設呼叫clone過程不知道什麼原因停掉了,可以呼叫 git svn fetch - 它會從上次中斷的地方繼續往下做

設定svn ignore檔案

由於svn可能有自定一些ignore的規則,因此當clone完之後,建議先把ignore加進來。

clone完直接使用:

git svn show-ignore >> .gitignore
    git add .gitignore
    git commit -m "加入svn ignore清單"

日常版控行為

抓下來之後,會發現其實整個svn的trunk、branch和tags都變成了git的遠端remote branch。

可以看到這個repo只有一個trunk,所以remote/svn/trunck
可以看到這個repo只有一個trunk,所以remote/svn/trunck

接下來就像日常使用git的方式使用 - 也可以使用gui工具例如source tree。

等到最後要準備上到svn的時候,需要先從svn抓最新的回來

從svn抓取最新

和同git遠端repo溝通一樣,在溝通前,要先做一次更新,確保本機和正式機器的版本是一樣新。

這個時候,可以呼叫:

git svn rebase

這個其實類似于git裡面的git pull --rebase

所以如果有發生衝突,同等於在rebase的時候發生衝突要處理的方式一樣。

把git的commit推上svn

假設沒有開branch,那麼再上一個步奏svn抓取最新的時候,會自動把master對最新的做rebase,因此不用做任何處理,直接呼叫:

git svn dcommit
即可

假設有開branch,那麼這個時候應該要用rebase+merge來達到master和branch 合併的時候會是 Fast Forward Merge:

git checkout branch1
   git rebase master
   git checkout master
   git merge branch1
   git svn dcommit

建立一個git repo mirror

到目前為止其實會發現,git svn只是有一個特殊的branch在記錄目前svn版本在哪裡,然後只有需要和遠端溝通的時候呼叫git svn相關指令,其他操作者一般git沒有兩樣。

這時候假設想要把目前記錄推送到某一個git repo上面,做法其實很簡單(就是一般加remote的方式):

  1. 加入一個remote - 例如 git remote add origin {{git repo url}}
  2. 然後push上去:git push -u origin master
在去哪個git repo看就會發現都上去了

結語

要換使用一個工具或方法通常都是因為有某些痛點和需求。因此從svn要轉git,先用這種方式,等到都確定要轉的時候,可以讓大家改成用那個git repo版本而把svn給停用掉。

另外一個常見的版控,TFS也有類似的bridge工具可以下載 - 運作原理和git svn差不多。

參考資料

Atlassian關於從Svn到Git的說明(英文)
很棒的一系列介紹如何從svn轉到git
git svn 指令(英文)
git svn每一個指令和參數的含義
官方介紹git svn
鏈接是中文內容
Migrating from SVN to Git, preserving branches and tags
不錯的概觀介紹。
第 29 天:如何將 Subversion 專案匯入到 Git 儲存庫
保哥30天git裡面關於和svn溝通的部分
標籤:

如果文章對您有幫助,就請我喝杯飲料吧
街口支付QR Code
街口支付QR Code
台灣 Pay QR Code
台灣 Pay QR Code
Line Pay 一卡通 QR Code
Line Pay 一卡通 QR Code
街口支付QR Code
支付寶QR Code
街口支付QR Code
微信支付QR Code
2017-06-25 Sunday
git
comments powered by Disqus