2016/10/11

Just a Note:Use GIT as SVN Client

2016.10.03 補充:
略過不要 fetch 的目錄。

當團隊中有人使用非 Windows 系統時,可能會發生 svn 中出現 Windows 無法接受的字元的目錄,
即使事後刪除了,但這樣的資訊仍會存在 history 中。

若此時使用 git svn 進行 fetch,便會發生無法建立目錄的錯誤。
此時可以透過 sparse checkout 避開這樣的目錄,具體步驟如下:

1. git config core.sparseCheckout true
2. 查看 .git/info 目錄下是否有 sparse-checkout 檔案,若無,新增一個。
3. 在檔案中加入
/*
!不要的目錄路徑

4. 重新執行 git svn rebase 或 git svn fetch

5. 即使加了上述的設定,在 git svn rebase 時,還是會有問題,此時就必須額外加上 --ignore-paths 忽略有問題的路徑:
git svn clone some_svn_url . -s --prefix=svn/ --ignore-paths="^(?:trunk|branches|tags)/不要的路徑"
git svn rebase --ignore-paths="^(?:trunk|branches|tags)/不要的路徑"


沒想到已經三年沒寫筆記了......





2013.10.11 補充:
避免 merge 後,對應的 svn url 被改變。

假設:
develop --> svn/branches/develop
master --> svn/trunk

進行以下操作:
1. git checkout master
2. git svn info (正確對應到 svn/trunk)
3. git merge develop
4. git svn info (變成對應到 svn/branches/develop,這樣是錯的)

修正:
step 3 改成 git merge develop --no-ff
git svn info (正確對應到 svn/trunk)



2013.10.09 補充:

同時 tracking 兩個 svn repository:
1. 假設核心模組的 svn repository 為 svn://svnserver/base,並且已經存在 branch。
2. 假設專案以核心模組為基礎進行開發,svn repository 為 svn://svnserver/project,沒有 branch。

3. 執行
git svn clone svn://svnserver/project -s --prefix=svn/
4. 此時 local master branch 對應到 svn://svnserver/project/trunk,.git/config 的內容如下,

[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true
hideDotFiles = dotGitOnly
[svn-remote "svn"]
url = svn://svnserver/project
fetch = trunk:refs/remotes/svn/trunk
branches = branches/*:refs/remotes/svn/*
tags = tags/*:refs/remotes/svn/tags/*


5. 手動修改 .git/config,將 base 的 svn server 加入,變成

[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true
hideDotFiles = dotGitOnly
[svn-remote "svn"]
url = svn://svnserver/project
fetch = trunk:refs/remotes/svn/trunk
branches = branches/*:refs/remotes/svn/*
tags = tags/*:refs/remotes/svn/tags/*
[svn-remote "svn2"]
url = svn://svnserver/base
fetch = trunk:refs/remotes/svn2/trunk
branches = branches/*:refs/remotes/svn2/*
tags = tags/*:refs/remotes/svn2/tags/*


6. 執行以下指令,將 svn://svnserver/base 的資料都 fetch 到 local。
git svn fetch --all

7. 執行以下指令,顯示內容大致如下(不包含括號內容,括號內是說明對應到的 svn url)
git branch -a

*master
 remotes/svn/trunk      (--> svn://svnserver/project/trunk)
 remotes/svn2/develop   (--> svn://svnserver/base/branches/develop)
 remotes/svn2/branch1   (--> svn://svnserver/base/branches/branch1)
 remotes/svn2/branch2   (--> svn://svnserver/base/branches/branch2)
 remotes/svn2/trunk     (--> svn://svnserver/base/trunk)


8. 若要以 base 的 develop branch 作為專案的 base,執行以下指令,
git merge remotes/svn2/develop





2013.10.05 補充:
1. about clone:避免未來操作 branch 時發生 Git: warning: refname 'xxx' is ambiguous 的問題。
git svn clone svn_url --stdlayout --prefix=svn/

參考:http://stackoverflow.com/a/5425585



2013.10.01 補充:

把 local 的 git branch 放到 svn server 上:

git checkout master
git svn branch <new_svn_branch_name>
git svn fetch
git branch -r # make sure <new_svn_branch_name> exists
git checkout -b tmp/svn-rebase-target <new_svn_branch_name>
git rebase --onto tmp/svn-rebase-target master <existing_git_branch_name>
# That should have checked out <existing_git_branch_name>.
git svn dcommit -n # This should say it'll commit to <new_svn_branch_name>.
git branch -D tmp/svn-rebase-target # clean up the temporary branch.
git svn dcommit

參考:http://barkingiguana.com/2010/03/03/creating-a-new-subversion-branch-from-an-existing-local-git-branch/




2013.08.29 補充:
1. about clone
若原本 svn 的目錄結構是 trunk, branches, tags 的標準目錄,可以使用下列指令進行 clone
git svn clone svn_url --stdlayout
如此一來,svn 的 trunk 會對應到 git 的 master branch、svn branches/tag 下的目錄會對應到 git 的 branch/tag name。

2. about svn relocate
假設 svn repository 從 A server 搬到 B server,svn 需做 relocate,而 git svn 的處理如下:
(1) 先查看 .git/svn/.metadata 檔案,把 reposRoot 和 uuid 記錄下來。reposRoot 此時會是 A server 的 url。
(2) 在 command line 執行以下指令:
git config svn-remote.svn.rewriteRoot [A server 的 repo url (原本的 repo url)]
git config svn-remote.svn.rewriteUUID [步驟(1) 中的 uuid]
git config svn-remote.svn.url [B server 的 repo url (新的 repo url)]
git svn rebase


參考:http://stackoverflow.com/a/4061493/2023612



操作步驟 (括弧內為對應 svn 的指令)

1. git svn clone svn_url (svn checkout -r 0)
會以 svn_url 的最後一段做為預設目錄名稱,建立一個受 git 控管的目錄,或是可以改下 git svn clone svn_url folder,便會建立指定名稱的目錄。這步驟只是讓 git 和 svn server 掛勾。

2. git svn rebase (svn update)
此步驟會逐一把每個 svn revision 的資料取回,所以如果 svn 的版本號已經很大,那這個程序就會跑很久。


3. modify code/document
程式或文件修改。

4. git add
不管是新增的資料要納入控管、或是修改既有的資料,都要針對該資料執行 git add。

5. git commit
commit to git。

6. git svn dcommit (svn commit)
將變更遞交回 svn server。


PS.
1. 步驟 1 只會做一次,每天工作的流程就是步驟 2~6。
2. 步驟 2, 6 是 git 與 svn server 的互動,不管在 local 執行了多少次 git commit,只有執行了步驟 6 才會把異動遞交回 svn server。
3. 步驟 3~5 算是很簡化的步驟,屬於 git 本身的操作,關於 git 的工作流程,可以參考 git flow 的方式。
4. 若所有變更都已經執行過 git commit,但執行步驟 6 時失敗,原則上就和 svn 相同,就是當最後一次從 svn server 取回資料後、到遞交變更前,有人遞交了新的版本到 svn server 上,此時:
 (1) 執行步驟 2 取回 svn server 上的最新資料
 (2) 如果 merge 成功就沒事,再執行步驟 6。
 (3) 如果步驟 2 發生衝突,修正完衝突後,重新執行步驟 4, 5, 6 遞交回 svn server。
5. 若有變更尚未執行 git commit,也暫時無法 commit,但卻要從 svn server 取的新的程式,此時:
 (1) git stash 把目前變更但未 commit 的資料暫存
 (2) git svn rebase 取得新程式
 (3) git stash apply 復原暫存 (可能會有衝突發生)
6. 在 Windows 下,步驟 4, 5 可使用 git gui 指令,會有視窗操作介面,可以不用打很多指令參數。
7. 不習慣下指令的人,在 Windows 下,一旦做完步驟 1,便可以用 TortoiseGit 完成所有其他步驟。
8. MAC 上頗負盛名的 sourcetree 也支援 Windows 了。基本上透過 sourcetree 存取 svn server 就是用 git svn (吧)。

目前感受較深刻的好處:
1. 不需連上 svn server 即可看到所有 commit 的歷程。(超重要)
2. 根據經驗,.git 目錄內的資料大小比 .svn 小很多。
3. 一套軟體同時支援 git 和 svn。

沒有留言:

張貼留言