2008年12月14日 星期日

迷人的 git

如果你常常寫 code,一定會遇到一種情況:寫改目前會動的 code,又怕會改壞…這時,就是 SCM (Source Code Management) 程式的時候了。

前一陣子,不知怎麼的,好幾個朋友問我,他們公司/專案要選 SCM,要選用那一個呢?

SCM 百百種… CVS SVN SVK Monotone bitkeeper git etc. etc.
要用那一個比較好呢?

在過去…我會說 SVN, SVN 比 CVS 方便多了,流水號的機制讓開發過程相當的清晰。
現在我強烈推薦 git
自從用了 git 之後~我已經離不開 git 了…

為什麼呢?
1. 因為我用 notebook 寫 code, 這表示我可能會在辦公室寫,在家寫,睡不著時在床上寫,在無聊的會議中寫,在坐車時寫,在山林中寫… 而且我寫的東西大多要merge 回 upstream。可是很多地方是沒有網路的。或是網路不好…如果我用SVN 的話…就必需開始用 quilt寫 patch 了…管理 Code 變得相當的麻煩。
Git 是一個分散式的 SCM,也就是在你目前工作的環境下,就是一個完整的 source code repository. 當你從網路上用 git 抓下 code 的同時,你已經把完整的開發 tree 抓回來,放在你的電腦之中了…而 commit code 時也是 commit 到你 local 端之中。所以你就可以一直寫,到處寫,直到你有網路之時再一次 push 回去…
2. 我很愛改 Code,而 git 的版本管理是用 patch 做出來的,也就是說 branch 會變得相當的容易。當我想做任何風險較大的變動時,可以先開一個 branch 出來,在裏面惡搞一翻。如果結果不錯的話,就 merge 回主要的 branch。
3. git 超級快,因為 git 把所有的 patch 都抓回來了,要做 diff ,翻 log 就變成超級快速而且穩定的事。
4. 支援 SVN 和 CVS,git-svn 可以把 svn 之中的所有 commit 變成 git 之中的一個 branch。
也就是不管upstream 用的是 SVN or CVS ,我都可以用 git 來管理。事實上,還有一些更好玩的玩法
5. SHA1-hash 的版本管理方式,讓 git 跳脫 SVN 之類強烈線性的版本管理…可以 rebase, cherry-pick ...
6. 開始一個 repository 超級方便,git init 就好了

Anyway 說了這麼多好處…怎麼用呢?就先給 link 嘍…
戒色夫 "我愛 Git"
Git User manual

我不打算在這寫另一個 manual 就寫幾個個人覺得很實用的 use cases.
1.做實驗
當你的 master branch 可以 run,但你想要對某個演算法大修時…
a. git checkout -b test_xxxx
b. 大修你的演算法…且 做細部的 commit,直到完成
c. git checkout master 回到本來的 master
d. git pull 把再新的 master 拉回來
e. git checkout test_xxxx
f. git rebase master 把再新的 master commit rebase 上去…可能會要解 conflict
(c, d, e, f, 可變成 git fetch origin/master; git rebase -i origin/master)
g. git checkout master
h.1 git rebase test_xxxx 把 test_xxxx 的東西再 rebase 過來
h.2 git cherry-pick xxxxxx 把某個 patch 挑過來
i. git push 把修改送回main stream

2.用 git-svn 搬 SVN repository
如 project P 要從 repository A 搬到 B 玩法如下
a. mkdir A_svn; pushd A_svn; git svn init http://A/trunk/ ;git svn fetch; popd
b git clone file://`pwd`/A_svn B_svn
c. cd B_svn; git svn init http://B/trunk/
d. git checkout -b master_tmp
e. git svn init http://B/trunk/ ; git svn fetch
f. git checkout -b svn --track git-svn
g. git checkout master; git rebase svn
h. git-rev-list master_tmp (suppose the last line is 532d2f35aa73331d409475efa84c00a1afa0e1a0)
i. git svn set-tree 532d2f35aa73331d409475efa84c00a1afa0e1a0
j. git rebase master_tmp; git svn dcommit

3. 粉飾太平
當 git commit 了一些笨笨的 code
可以用 git rebase -i xxxx 來拿掉/合並 一些 commit

3 則留言:

walkingice 提到...

推「粉飾太平」,我笑了 XDXDXD

iveney 提到...

haha, 看完你这篇今天试用了一下GIT,果然不错 :)

Kenneth_YITA 提到...

我還是不會用GIT....@@"