-- 故國神遊,多情應笑我,早生華髮。html
Git是一個版本控制工具,代碼管理工具,團隊協做工具。它跟SVN等傳統工具實現一樣的目的;但從某種程度來講,它更快,更靈活。我想絕大多數讀者都已經在接觸這個工具了,而且用於平常的項目中去了。個人這篇文章,不是做爲一個Git入門教程,也不是做爲一本大塊頭的教科書。(說到教科書,我推薦下面的這本。這本書確實好,很全面。個人這篇文章,其實就是這本書的讀書筆記而已。)java
Pro Git -- http://git.oschina.net/progit/git
接着說。個人這篇文章,主旨在於啓發你們超越平時的使用侷限,從另外一種視角去看待Git和使用Git,讓人有一種「啊哈,Git也能這麼用「的感受。這有點王婆賣瓜的味道了,這我必須認可。程序員
不少項目組,對於剛入職的程序員,會像下面這樣對他們普及Git的知識:redis
#使用git clone克隆項目的代碼 git clone https://your-project-address #使用git add添加修改的文件 git add your-filename #或者使用git add --all添加全部修改的文件 git add --all #使用git commit提交代碼到本地的代碼庫 git commit -m some-description-message #使用git push提交代碼到遠程的代碼庫 git push
#使用git pull拉下遠程代碼庫中更新的代碼
git pull
僅使用這五個命令,確實就足夠進行團隊協做了。這是使用Git的一種模式,並且無可厚非。不過,這樣作有種僅僅把Git當成了純粹的代碼共享庫的感受,多多少少顯得有點不大規範。其實,Git有更加豐富的能力,它能讓你的項目開發有更加規範的流程,整個項目歷史有更加清晰的追溯,分工協做上也更加井井有理。併發
Git的特點有哪些呢?app
Git的最大特點可能就是做爲一款分佈式代碼管理工具了。Git的絕大部分操做都是在本地進行的,這使得Git更快,並且更靈活。更靈活是由於在你的改動被提交到遠程代碼庫以前,你能夠在本地進行任意的操做。另外一方面,這也意味着改動提交到遠程被共享以後,就不方便再改動舊的提交歷史了。因此,請慎重上傳改動到遠程。編輯器
代碼的提交歷史是一個項目開發歷程的記錄。這其中不只僅是情懷的記錄。更重要的是,提交歷史給了咱們項目回溯的能力,從而讓咱們可以找出問題代碼的來源,並修正它。Git的提交歷史很強大,咱們能夠去翻看歷史,還能附加上豐富的篩選條件;甚至能夠修改有問題的歷史。爲了更好地利用Git的歷史功能,咱們要時刻保持提交歷史的細緻與乾淨。這意味着,咱們要恰到好處地提交咱們的代碼,以及給它一個恰到好處的描述。分佈式
Git的另外一特點就是分支了。簡單地說,分支就是不一樣的代碼故事。它們相互區別又互有聯繫,漸行漸遠又能在某一處匯合。使用分支,咱們可以控制代碼的不一樣走向,從而很好地安排咱們的開發工做。靈活使用分支能夠簡化咱們的不少工做。ide
說Git簡單,聽起來有點怪怪的。若是你要了解Git 內部原理,那確實夠複雜的。不過,Git的特點在於,即便你不瞭解這些原理,你仍然能夠靈活運用它。只用去學Git的一些基本的概念就足夠了,例如倉庫,暫存,提交,歷史,分支等。說實話,我到如今是說不出這些概念的具體定義的,並且也只是淺要地瞭解了下這些概念的原理。可是,這並不影響我去使用它。Git的特點在於,學些基本的概念和原理;剩下的,去用就夠了。這讓我想起了不少的Unix工具,如Vim,LaTex等,以及Unix哲學。
所謂Git哲學,是指使用Git的思惟方式。下面是我以爲的Git哲學中最要緊的幾點:
若是說提交歷史是一個版本控制工具最核心的模塊,我以爲一點也不爲過。代碼的提交歷史要涵蓋到具體的每一次改動,而且要有清晰一致的描述。這要求咱們:
每次的提交得是一個具體的總體。所謂具體的,是指你的提交不能是一次籠統的或歸納的改動;所謂總體,是指你的提交是一個已經完成的改動,而不能是懸而未決的。其實,這兩點能夠從你的提交說明中檢驗出來:
其實作到這一點也很容易 --
儘量得多提交,儘量得早提交,當完成一個小的功能點時就提交。
描述應該簡潔明瞭。簡潔是指可以用一句話描述你作的事情,而且不要覆蓋其餘沒必要要的信息;明瞭是指絕對不能含糊,不只你能看得懂,也要讓局外人也能看得懂。我列了幾個要點:
因爲每一個提交都是一個細緻的改動單元,當項目進行到必定階段,整個提交歷史必定會顯得很長。這時候你可能會以爲提交不少很雜,會淹沒一些重要的版本發佈提交,例如上線的版本v1.0,v1.1。我想這是沒必要要的擔憂,認真地對待提交歷史,會讓整個提交歷史顯得多而不雜。並且,徹底能夠爲重要的提交打標籤。請記住 git tag 命令,它能夠爲重要的提交打標籤。
Git的提交歷史是至關靈活的。你能夠查看歷史;更厲害的,你還能夠去修改它。因此,你能夠在任意時刻去修正你的歷史。這裏有個例外,就是你沒法修改遠程倉庫的提交歷史。一方面,有的遠程代碼倉庫不支持提交歷史的修改;另外一方面,即便支持修改歷史,這樣的修改也會對其餘開發者形成混亂。關於遠程提交的準則是:
-- 一個分支就是一個故事,一個劇情。使用分支是爲了避免讓第三者破壞完美的劇情。
要有意識地去使用多分支,而不是去忽略它。能夠在下面的狀況下考慮使用分支:
這兩個使用分支的策略都是本地臨時分支使用策略。不管是添加特性分支仍是BUG修復分支,它們都有存在週期短的特色,而且都只是爲解決某個特定問題而存在的。當這個問題被解決之後,它們就要被併入到主分支,這樣就完成了本身的歷史使命。使用分支的一種狀況是:當你要同時進行多個任務的時候。
不管是主分支,仍是上面的特性添加分支或者BUG修復分支,都是你本身一我的的任務。你要同時完成兩個或者三個任務。這時候纔是分支發揮它最大做用的時候。不要在一個分支裏同時作這幾件事情,這樣會違反第一哲學。記住:
每次只作一個任務;若是不得已要臨時切換到其餘任務,請使用分支。
Git既存在本地分支也存在遠程分支;擅用分支,實際指的是靈活運用本地分支,而不是濫用遠程分支。你能夠隨意地建立本地分支,頻繁地在多個分支的下來回工做。但不要把這一切牽扯進遠程分支。通常來講,遠程分支是長期分支,是做爲項目不一樣的發展階段或者發展路線而存在的。例如穩定版、開發版、激進版等。這通常是項目決策者操心的事情。
再囉嗦一句:若是分支再也不須要了,就刪除它。
私有化意味着封裝。相似於面向對象上的封裝,團隊協做上也有封裝的概念。你能夠在本地靈活地使用Git的各類操做,而不會對他人形成任何影響。不過這種靈活性應侷限於本地,而不要將冗餘公開給遠程的共享庫。這方面有些準則,其中有些是對上面兩個哲學的總結,以下:
體現Git哲學的最好方式就是實踐它,用Git的方式去工做,學會使用Git思惟。接下來我會涉及到具體的Git操做。
【這一部分純當是複習。】
初始化一個新倉庫:
git init
從現有倉庫克隆:
git clone <your-project-address>
時刻檢查目錄狀態:
git status
.gitignore 文件能夠聲明脫離版本控制的文件:
#haha
暫存修改:
git add <new-file-or-modified-file> git add --all
若是不當心 git add 了某個文件,使用 git rm 從暫存區移除(附帶--cached參數移除跟蹤但不刪除文件,以便稍後在 .gitignore
文件中補上):
git rm --cached <your-added-file>
想知道代碼作了哪些改動(會精確到行),使用:
git diff <some-file> git diff #這會顯示全部文件的改動
上面的命令是顯示工做目錄中當前文件和暫存區域快照之間的差別;若是想知道暫存區域與最近一次提交之間的差別,附加 --cached 參數:
git diff --cached <some-file> git diff --cached
提交更新:
git commit #這會爲你打開一個文本編輯器
git commit -m <your-commit-message>
爲了更好地說明用法,我使用了JFinal項目的Git源碼做爲例子。
使用 git log 能夠查看提交歷史。你應該看到相似於下面的結果:
$ git log
commit 121e247032be9e4d6a3c7eb8035914f59857c43d Author: James <jfinal@126.com> Date: Sun Jul 26 13:40:44 2015 +0800 修改變量名,actoin 改成 action commit d330532f9db493034578d5dac1ece43c65136569 Author: James <jfinal@126.com> Date: Sun Jul 26 11:00:55 2015 +0800 變量名修改
能夠看到SHA-1 校驗和,做者的信息,時間以及提交說明。Git使用校驗和來指代每一次提交,例如輸出第一行的 121e247032be9e4d6a3c7eb8035914f59857c43d 。另外,若是不產生歧義的話,能夠用校驗和的前幾個字符來指代提交,例如 121e247032be9e4d6a3c 和 121e247032 。
若是想看某一次具體的提交,指明它的校驗和便可:
$ git log d330532f9 commit d330532f9db493034578d5dac1ece43c65136569 Author: James <jfinal@126.com> Date: Sun Jul 26 11:00:55 2015 +0800 變量名修改 commit cdec1c3ceaceecfa4297c72efd8d8095640757f8 Author: James <jfinal@126.com> Date: Thu Jul 16 10:10:49 2015 +0800 修改 Cache.expireAt(...) 方法上的註釋
這會顯示從指定提交開始往前回溯的提交歷史。若是隻是想顯示指定的這一個提交,用 -1 參數( -2 則顯示兩次提交,依次類推):
$ git log d330532f9 -1 commit d330532f9db493034578d5dac1ece43c65136569 Author: James <jfinal@126.com> Date: Sun Jul 26 11:00:55 2015 +0800 變量名修改
使用 git log --pretty=oneline 能夠顯示更緊湊的提交信息,每次提交用一行來顯示:
$ git log --pretty=oneline 121e247032be9e4d6a3c7eb8035914f59857c43d 修改變量名,actoin 改成 action d330532f9db493034578d5dac1ece43c65136569 變量名修改 cdec1c3ceaceecfa4297c72efd8d8095640757f8 修改 Cache.expireAt(...) 方法上的註釋 749fbe0d8e9da0e33fe2b30085f7467e86881e17 JFinal 2.0 release ^_^ 52633ce2da704cf35a48aa9b8a1afe99d6c2ed1d JFinal 2.0 release ^_^ 1e00c07348bd7b1ed16bb5c224e0a0de67b9b13b JFinal 2.0 release ^_^ 0330d7ed5f3d742eaca201456927d9cecb40e215 JFinal 2.0 release ^_^ aa4a95af60a1dc12dfd649bd208de473dcfb369f jfinal 1.9 release ^_^ af6469eb6f49c23cba8215f2b0e9c8d51cd5f8c9 jfinal 1.9 release ^_^ 4ab71ce41cca8b7d16bef89655b51e6de6548d30 jfinal 1.9 release ^_^ 03a3c5a2bdb848ad2f9a30e29eba4f468176497f jfinal 1.9 release ^_^
使用 -p 選項展開每次提交所作的修改。例如咱們使用下面的命令展開哈希前綴爲 d330532f9 的那次提交的修改:
$ git log d330532f9 -p -1 commit d330532f9db493034578d5dac1ece43c65136569 Author: James <jfinal@126.com> Date: Sun Jul 26 11:00:55 2015 +0800 變量名修改 diff --git a/.gitignore b/.gitignore index 416db66..b1e58ba 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ integration-repo /build/ # IDEA metadata and output dirs +/.idea/^M *.iml *.ipr *.iws diff --git a/src/com/jfinal/config/Routes.java b/src/com/jfinal/config/Routes.ja index fab2604..8ad1b03 100644 --- a/src/com/jfinal/config/Routes.java +++ b/src/com/jfinal/config/Routes.java @@ -86,11 +86,11 @@ public abstract class Routes {
使用 --stat 選項僅顯示代碼修改的統計信息(僅顯示簡要的增刪行數統計,特別適合做代碼審查):
$ git log --stat commit 121e247032be9e4d6a3c7eb8035914f59857c43d Author: James <jfinal@126.com> Date: Sun Jul 26 13:40:44 2015 +0800 修改變量名,actoin 改成 action src/com/jfinal/core/ActionMapping.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) commit d330532f9db493034578d5dac1ece43c65136569 Author: James <jfinal@126.com> Date: Sun Jul 26 11:00:55 2015 +0800 變量名修改 .gitignore | 1 + src/com/jfinal/config/Routes.java | 6 +++--- src/com/jfinal/plugin/activerecord/Sqls.java | 4 ++-- src/com/jfinal/plugin/activerecord/tx/TxByMethods.java | 14 +++++++------- src/com/jfinal/plugin/redis/RedisInterceptor.java | 11 ++++++++++- 5 files changed, 23 insertions(+), 13 deletions(-)
我從《Pro Git》中摘出了一些選項及說明:
選項 說明 -p 按補丁格式顯示每一個更新之間的差別。 --stat 顯示每次更新的文件修改統計信息。 --shortstat 只顯示 --stat 中最後的行數修改添加移除統計。 --name-only 僅在提交信息後顯示已修改的文件清單。 --name-status 顯示新增、修改、刪除的文件清單。 --abbrev-commit 僅顯示 SHA-1 的前幾個字符,而非全部的 40 個字符。 --relative-date 使用較短的相對時間顯示(好比,「2 weeks ago」)。 --graph 顯示 ASCII 圖形表示的分支合併歷史。 --pretty 使用其餘格式顯示歷史提交信息。可用的選項包括 oneline,short,full,fuller 和 format(後跟指定格式)。
Git提交歷史的一大特點在於能夠按照條件篩選歷史。例如篩選出最近兩週到最近一週的提交歷史:
$ git log --since=2.weeks --until=1.weeks commit cdec1c3ceaceecfa4297c72efd8d8095640757f8 Author: James <jfinal@126.com> Date: Thu Jul 16 10:10:49 2015 +0800 修改 Cache.expireAt(...) 方法上的註釋
我也列出了一些可以設置篩選條件的一些選項,一樣來源於《Pro Git》:
選項 說明 -(n) 僅顯示最近的 n 條提交 --since, --after 僅顯示指定時間以後的提交。 --until, --before 僅顯示指定時間以前的提交。 --author 僅顯示指定做者相關的提交。 --committer 僅顯示指定提交者相關的提交。 -- 命令的最後一個選項,後跟路徑名錶示只關心某一路徑下的提交歷史
Git提交歷史的另外一大特點在於你能夠修改它。不過格外注意的是,不要修改那些已經推送到遠程版本庫的提交歷史。
首先介紹如何撤銷。這多少與修改歷史無關,由於此時的歷史可能還未造成。
若是隻是但願將某個文件的改動從暫存區拿出來,而保持文件原有內容不變,使用命令:
git reset HEAD <your-file>
其中HEAD指代最近一次提交(*)。你可使用HEAD變量來避免使用哈希值。
下述命令會令整個項目的狀態回退(保留修改):
git reset HEAD
若是想將文件恢復到最近一次提交的版本,使用命令 git checkout 。這會使得其從暫存區拿出來(若是已經存入暫存區),而且文件內容恢復到最近一次提交的狀態:
git checkout <your-file>
若是想直接撤銷全部改動(包括修改),使用命令:
git reset --hard HEAD #恢復全部改動到最近一次提交
git reset --hard HEAD~1 #恢復全部改動到最近一次提交的上一次提交
git reset --hard HEAD~2 #恢復全部改動到最近一次提交的前兩次提交
git reset --hard d330532 #恢復到指定提交
帶有 --hard 選項的版本回退是一個不可恢復的操做,請謹慎用之。
當咱們完成提交後,發現漏掉了某些改動(例如忘記添加相應的API註釋)。這時咱們固然能夠將改動做爲一次新的提交提交一發。不過,還有其餘的方案,即將漏掉的改動從新補回到對應的歷史提交中,畢竟漏掉的改動確實是那次提交的一部分。Git給了咱們修改提交的能力。
若是隻是要修改最近的一次提交,使用 git add 命令暫存相應的改動,而後輸入命令 git commit --amend 。這會把你代入修改提交說明的編輯器中。保存後退出,咱們就完成了咱們的提交修改。
若是隻是想修改最近一次提交的提交說明,直接輸入 git commit --amend ,而後進入編輯器修改提交說明並保存退出便可。
要修改歷史中更早的提交,就要用到 git rebase -i 交互式的提交歷史修改工具。我在命令行中輸入:
git rebase -i HEAD~4
它會帶我進入一個文本編輯器中(在個人系統裏意外地是VIM)。關注前四行,會看到咱們能夠修改最近的四次提交歷史( HEAD~4 指定)。其中提交由早到晚地排列,與 git log 顯示順序相反。
1 pick 749fbe0 JFinal 2.0 release ^_^ 2 pick cdec1c3 修改 Cache.expireAt(...) 方法上的註釋 3 pick d330532 變量名修改 4 pick 121e247 修改變量名,actoin 改成 action
這時咱們能夠修改某次提交,例如修改第2行的提交,只需將 pick 換成 edit 便可。而後保存並退出編輯器。
pick 749fbe0 JFinal 2.0 release ^_^ edit cdec1c3 修改 Cache.expireAt(...) 方法上的註釋 pick d330532 變量名修改 pick 121e247 修改變量名,actoin 改成 action
像以前同樣,使用 git commit --amend 修改提交;最後使用 git rebase --continue 完成修改任務。
咱們也能夠刪除某個提交,只需將相應的提交行刪掉便可。例如刪除第2行的提交:
pick 749fbe0 JFinal 2.0 release ^_^ pick d330532 變量名修改 pick 121e247 修改變量名,actoin 改成 action
從新排列提交也是OK的。只須要從新排列便可。例以下面的編輯把最近一次提交移到最前,最先的一次提交移到最近:
pick 121e247 修改變量名,actoin 改成 action pick cdec1c3 修改 Cache.expireAt(...) 方法上的註釋 pick d330532 變量名修改 pick 749fbe0 JFinal 2.0 release ^_^
一個有用的功能是壓制提交,即把多個提交合併成一次提交。例以下面的編輯將多個描述都爲」JFinal 2.0 release ^_^「的提交合併爲一個提交:
pick 0330d7e JFinal 2.0 release ^_^ squash 1e00c07 JFinal 2.0 release ^_^ squash 52633ce JFinal 2.0 release ^_^ squash 749fbe0 JFinal 2.0 release ^_^ pick cdec1c3 修改 Cache.expireAt(...) 方法上的註釋
相應地,能夠拆分一個提交。它的技巧在於 edit 某次提交,而後調用 git reset HEAD^ 回到父提交,而後再屢次 git commit 便可。
git reset HEAD^ git add file1 git commit -m "add file1" git add file2 git commit -m "add file2" git rebase --continue
當準備進入交互式rebase工具時,若是當前的工做區存在修改而沒有被提交,則會被禁止進入。此時咱們能夠先將修改提交;有時又不但願這麼作,可能咱們的代碼改動還不能構成一個完整的提交。咱們只但願先保存本身的工做,而後在須要的時候釋放出來。這時就用到 git stash 命令了。
咱們能夠將改動保存在一個棧中,稱之爲儲藏(Stashing):
git stash
而後查看棧狀態:
$ git stash list stash@{0}: WIP on master: 121e247 修改變量名,actoin 改成 action
由於是棧,能夠屢次調用 git stash ,而後查看棧狀態:
$ git stash list stash@{0}: WIP on master: 121e247 修改變量名,actoin 改成 action stash@{1}: WIP on master: 121e247 修改變量名,actoin 改成 action stash@{2}: WIP on master: 121e247 修改變量名,actoin 改成 action
而後在適當的時候,釋放一個儲藏。既能夠釋放指定的儲藏,例如 stash@{0} 、 stash@{1} 、 stash@{2},也能夠默認釋放最近的儲藏(stash@{0}):
git stash apply git stash apply stash@{2}
當儲藏再也不須要時,刪除它:
git stash drop stash@{2}
或者當即釋放最近的儲藏並刪除它:
git stash pop
儲藏的典型應用場景是當工做區有未提交的修改時,要切回到舊提交去修改( git rebase -i )或者切換到其餘分支( git checkout )。
Git的分支是從某個分支引出的一個分叉。在Git中建立分支時,必定是以某個分支爲基準,這個分支就是你當前工做的分支。
要查看當前在哪一個分支下工做,輸入命令:
git branch
此時會列出全部本地分支,行首標有*號的是當前工做分支。
建立分支:
git branch <new-branch-name>
切換到新分支:
git checkout <new-branch-name>
同時建立及切換分支:
git checkout -b <new-branch-name>
合併分支:
git checkout master
git merge <new-branch-name>
這能保證將新分支的改動合併到主分支。
刪除分支:
git branch -d <new-branch-name>
只有已被合併的分支才能順利刪除,不然會提示錯誤。
若是要強制刪除分支,使用命令:
git branch -D <new-branch-name>
以上只是分支的基本操做命令。要想活用這些命令,就要知道分支的使用思惟。分支的使用思惟,我以爲就是一句話,重複以前的一句話:
當你要放下手中的任務,臨時切換到其餘任務時,使用分支。
我這裏想舉一個關於分支使用的簡單的不能再簡單的例子。
首先你在進行master上進行主線開發,實現功能點一。忽然你臨時接到任務,完成功能點二,並立刻上線。此時你不得不放下手中的工做,投入到實現功能點二中去。
這時,你首先要作的是保存你正在進行的工做以便未來能夠恢復。可使用儲藏 git stash 或者臨時提交你的代碼以在未來經過 git commit --amend 修改你的歷史。這裏假設你使用的是儲藏。
而後新建分支並切換到新分支工做:
git checkout -b feature2
當你完成功能點二的開發時,提交你的代碼:
git add --all git commit -m "finish feature 2"
以後切換到主分支,合併feature2分支:
git checkout master
git merge feature2
改動能夠提交到遠程上線:
git push
而後你可使用 git stash pop 恢復你的工做。
隊伍中的長期分支控制了不一樣的開發進度。通常來講,應該有一個穩定分支和開發分支:你能夠將master做爲穩定分支,並配有一個develop分支;或者反過來,將master做爲開發分支,並配有一個stable分支。這裏假設master是穩定分支,而develop是開發分支。develop分支通常比master要超前,而且當測試穩定後纔會併入到master分支發佈。因此通常的工做流程就是:
在develop分支開發,測試穩定後併入到master分支發佈
另外,若是已發佈的版本遭遇到一個緊急BUG亟待修復,這時你應該保存develop分支的工做,而後切換到master分支去修復。由於要緊急發佈,你應當切換到穩定的master分支完成BUG修復,而不是基於不穩定develop分支。當修復完畢併發布後,再回到develop分支恢復工做。
利用分支,咱們能夠很好地分離了咱們的不一樣工做,不讓它們相互干擾,從而減小bug的來源;利用歷史,咱們能夠追蹤代碼的變化,爲咱們找出問題代碼提供了途徑。其實Git也爲咱們提供了其餘的好用的工具,利於咱們調試。
git blame
:誰動了個人代碼你是否會驚奇你的代碼爲何忽然變成這副模樣?不要緊,使用 git blame 命令能夠顯示你的代碼是誰最後修改的。命令格式:
git blame -L 12,22 simple.rb
能夠顯示文件simple.rb的第12至22行這塊代碼最後是誰、何時修改並提交的。
還有一個有趣的命令是 git bisect 。它能夠以二分查找的策略逐步逼近你在乎的壞代碼的來源。
首先輸入 git bisect start 來啓動二分查找。
輸入 git bisect bad 來告知當前的提交已是問題提交了。
而後輸入 git bisect good <good-commit> 來告知你知道的最晚的正常提交。
接着就能夠肯定壞代碼的來源在<good-commit>和當前提交之間,二分查找策略就能夠開啓了,這時Git監測處於中間的一個提交。假設從<good-commit>到當前提交一共有12個提交,記編號爲0、一、…、11. 這時咱們檢出的提交應該是6.
你能夠輸入 git bisect good 來告知這個提交是正常的,這樣它會捨棄編號爲0、一、…、6的提交;也能夠輸入 git bisect bad 來告知問題依然存在,這樣它會捨棄編號爲七、八、…、11的提交。而後繼續二分策略…一直到咱們只剩下一個問題提交的時候。這個提交就是咱們的問題提交的最初來源。
當你完成的時候,應該運行 git bisect reset 從新回到最初的地方。
Git是偉大的,但咱們依然要超越Git;畢竟Git只是一個工具,而咱們是使用工具的人。Git的功能是代碼管理和版本控制,但Git的本質在於其重視團隊,重視協做的開發精神。它重視協做,但又不束縛我的的創造。它使得每一個人均可以自由地編碼,同時又保持整個項目開發的協調一致。