git是一個實用的工具,在工作中,用得好,它能極大的提升你的工作效率;但用不好,它同樣會給你帶來麻煩,這一點我們在上一篇中有過詳細的描述。除了使用的規范性(git工作流)以外,在這一篇里,我會繼續延伸我對git的理解,希望能夠進一步打開你的腦洞,讓你和它之間的距離更近。
在互聯網公司,我認為git就是產品的中心,經驗證明,所有脫離git而獨立存在的協同軟件都是難以維護的,例如我以前就用trello或禪道在公司里推廣敏捷開發模式,用它們建立項目、拆分需求、分配任務,并專門給團隊進行培訓這些工具的使用方法。但最終都以失敗告終,具體原因是開發者總是忘了去這些協同軟件上修改狀態,每次都需要我來提醒,久而久之,就造成了協同軟件上的項目進度和實際進度不一致的情況,最后只好放棄使用。
深入追究這些工具不能持之以恒的原因,可能是因為這些辦公軟件并沒有幫助大家提升工作效率,反而卻增加了工作量,本來一次提交就意味著完成了任務,現在還要多出一步去打開一個頁面,并修改其中的狀態。
程序員都是很懶的。
所以理想的程序員會說,如果我提交一次,就完成了任務狀態的修改,那該多好,如果這樣,根本就不存在額外的推廣其他項目管理軟件的必要嘛。當想到這一點的時候,我突然明白了這不就是程序員必須具有的思維嗎,原來自己很長時間還沒有掌握這種思維。
最終,在近一年的工作中,我用這種方法逐漸的改善了以往的工作模式,即
能一步操作的事情,不要變成兩步來完成。
換句話說,既然git是程序員工作中的“必經之路”,那git一定就是連接其他一切的橋梁,我想,這應該也就是為什么有持續集成(continuous integration)這個概念的原因吧。具體一點,也就是利用git hooks的功能,在進行git操作后,執行一系列的事件,例如調用Trello的接口,修改任務的狀態為已完成或已解決,這樣做的好處也非常美好——它可以把一次提交和一個任務緊緊的聯系在一起,而不會出現提交了很多次之后,都不知道哪一次提交修改了哪些代碼的情況。
當然,如果你使用gitlab或github,上面說的把任務和編碼關聯在一起的功能,已經是這些軟件自帶的了,所以,我們現在使用gitlab,在gitlab上建立任務(issue)、開分支、編碼、提交、合并,完成后,任務會自動關閉掉,這個流程沒有任何一個多余的動作,也是理想的程序員希望達到的工作流程,詳細細節可以閱讀上一篇文章。
同樣的原理,我們可以在一次提交后做更多的事情,例如完成持續集成的幾個基本的步驟:
- 編譯
- 測試
- 打包
- 發布
實現方式同樣也是實現一個git hooks,當然這個世界上的很多輪子已經造好了,例如gitlab CI、Jenkins就是這樣的輪子,我們直接使用就行,如果理解了原理,肯定會更加得心應手。
下面是我編寫的一段go語言環境的gitlab CI腳本,通過它,你就可以一鍵完成項目的編譯、測試、打包這些過程了
# .gitlab-ci.yml
before_script:
- PRJ_NAME=my_project
- PRJ=$GOPATH/src/$PRJ_NAME
- rm -f $PRJ
- ln -s $CI_PROJECT_DIR $PRJ
- PATH=$PATH:$GOROOT/bin:$GOPATH/bin
stages:
- build
- release
- test
build:
stage: build
tags:
- golang
script:
- cd $PRJ
- make release
except:
- tags
release:
stage: release
artifacts:
name: "${PRJ_NAME}_${CI_COMMIT_REF_NAME}"
paths:
- build/
script:
- cd $PRJ
- git submodule init
- git submodule update
- make release
tags:
- golang
only:
- tags
test:
stage: test
tags:
- golang
script:
- cd $PRJ
- make test
except:
- tags
以上代碼中,before_script
是初始化go的環境,stages
告訴CI程序,要執行以下3個步驟:
- build——編譯
- release——打包
- test——測試
后續的以build
、release
、test
開頭的代碼段,便是具體的這些步驟所需執行的代碼,可以看到這幾個步驟所執行的核心腳本是調用Makefile
,執行make release
和make test
,最大的區別是,release只有在打tag
的時候才執行,而其他兩項是在不打tag
的時候執行的。
也就是說,這個CI腳本完成了2個功能:
- 在日常提交時,gitlab會對代碼進行編譯和測試,確保該提交是通過了編譯和測試兩個環節的。
- 在發版前,項目經理會在
production
分支上打一個tag
,這個動作會觸發release
環節的執行,會把build目錄下的文件打包成一個帶有版本號的壓縮包,同時產生一個可下載的http鏈接,這樣做的好處也非常明顯,在服務器開發中,我覺得最大的好處是把開發和運維解耦了,這兩個部門間再也不會扯皮了。
通過這三篇文章,你應該對git由淺入深的有了一些認識,可以看到git對團隊協作、團隊成員間工作的透明性的威力很大,減少了噪音的同時,讓團隊更專注于核心的代碼層面上,這也是git的作者Linus所提倡的:
Talk is cheap, read the f**king code.