git是一個(gè)實(shí)用的工具,在工作中摊沉,用得好,它能極大的提升你的工作效率痒给;但用不好说墨,它同樣會(huì)給你帶來麻煩,這一點(diǎn)我們?cè)?a href="http://www.reibang.com/p/acaa6452d178" target="_blank">上一篇中有過詳細(xì)的描述苍柏。除了使用的規(guī)范性(git工作流)以外尼斧,在這一篇里,我會(huì)繼續(xù)延伸我對(duì)git的理解试吁,希望能夠進(jìn)一步打開你的腦洞突颊,讓你和它之間的距離更近。
在互聯(lián)網(wǎng)公司,我認(rèn)為git就是產(chǎn)品的中心律秃,經(jīng)驗(yàn)證明爬橡,所有脫離git而獨(dú)立存在的協(xié)同軟件都是難以維護(hù)的,例如我以前就用trello或禪道在公司里推廣敏捷開發(fā)模式棒动,用它們建立項(xiàng)目糙申、拆分需求、分配任務(wù)船惨,并專門給團(tuán)隊(duì)進(jìn)行培訓(xùn)這些工具的使用方法柜裸。但最終都以失敗告終,具體原因是開發(fā)者總是忘了去這些協(xié)同軟件上修改狀態(tài)粱锐,每次都需要我來提醒疙挺,久而久之,就造成了協(xié)同軟件上的項(xiàng)目進(jìn)度和實(shí)際進(jìn)度不一致的情況怜浅,最后只好放棄使用铐然。
深入追究這些工具不能持之以恒的原因,可能是因?yàn)檫@些辦公軟件并沒有幫助大家提升工作效率恶座,反而卻增加了工作量搀暑,本來一次提交就意味著完成了任務(wù),現(xiàn)在還要多出一步去打開一個(gè)頁面跨琳,并修改其中的狀態(tài)自点。
程序員都是很懶的。
所以理想的程序員會(huì)說脉让,如果我提交一次桂敛,就完成了任務(wù)狀態(tài)的修改,那該多好溅潜,如果這樣术唬,根本就不存在額外的推廣其他項(xiàng)目管理軟件的必要嘛。當(dāng)想到這一點(diǎn)的時(shí)候伟恶,我突然明白了這不就是程序員必須具有的思維嗎碴开,原來自己很長時(shí)間還沒有掌握這種思維。
最終博秫,在近一年的工作中潦牛,我用這種方法逐漸的改善了以往的工作模式,即
能一步操作的事情挡育,不要變成兩步來完成巴碗。
換句話說,既然git是程序員工作中的“必經(jīng)之路”即寒,那git一定就是連接其他一切的橋梁橡淆,我想召噩,這應(yīng)該也就是為什么有持續(xù)集成(continuous integration)這個(gè)概念的原因吧。具體一點(diǎn)逸爵,也就是利用git hooks的功能具滴,在進(jìn)行g(shù)it操作后,執(zhí)行一系列的事件师倔,例如調(diào)用Trello的接口构韵,修改任務(wù)的狀態(tài)為已完成或已解決,這樣做的好處也非常美好——它可以把一次提交和一個(gè)任務(wù)緊緊的聯(lián)系在一起趋艘,而不會(huì)出現(xiàn)提交了很多次之后疲恢,都不知道哪一次提交修改了哪些代碼的情況。
當(dāng)然瓷胧,如果你使用gitlab或github显拳,上面說的把任務(wù)和編碼關(guān)聯(lián)在一起的功能,已經(jīng)是這些軟件自帶的了搓萧,所以杂数,我們現(xiàn)在使用gitlab,在gitlab上建立任務(wù)(issue)矛绘、開分支耍休、編碼刃永、提交货矮、合并,完成后斯够,任務(wù)會(huì)自動(dòng)關(guān)閉掉囚玫,這個(gè)流程沒有任何一個(gè)多余的動(dòng)作,也是理想的程序員希望達(dá)到的工作流程读规,詳細(xì)細(xì)節(jié)可以閱讀上一篇文章抓督。
同樣的原理,我們可以在一次提交后做更多的事情束亏,例如完成持續(xù)集成的幾個(gè)基本的步驟:
- 編譯
- 測(cè)試
- 打包
- 發(fā)布
實(shí)現(xiàn)方式同樣也是實(shí)現(xiàn)一個(gè)git hooks铃在,當(dāng)然這個(gè)世界上的很多輪子已經(jīng)造好了,例如gitlab CI碍遍、Jenkins就是這樣的輪子定铜,我們直接使用就行,如果理解了原理怕敬,肯定會(huì)更加得心應(yīng)手揣炕。
下面是我編寫的一段go語言環(huán)境的gitlab CI腳本,通過它东跪,你就可以一鍵完成項(xiàng)目的編譯畸陡、測(cè)試鹰溜、打包這些過程了
# .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的環(huán)境丁恭,stages
告訴CI程序曹动,要執(zhí)行以下3個(gè)步驟:
- build——編譯
- release——打包
- test——測(cè)試
后續(xù)的以build
、release
牲览、test
開頭的代碼段仁期,便是具體的這些步驟所需執(zhí)行的代碼,可以看到這幾個(gè)步驟所執(zhí)行的核心腳本是調(diào)用Makefile
竭恬,執(zhí)行make release
和make test
跛蛋,最大的區(qū)別是,release只有在打tag
的時(shí)候才執(zhí)行痊硕,而其他兩項(xiàng)是在不打tag
的時(shí)候執(zhí)行的赊级。
也就是說,這個(gè)CI腳本完成了2個(gè)功能:
- 在日常提交時(shí)岔绸,gitlab會(huì)對(duì)代碼進(jìn)行編譯和測(cè)試理逊,確保該提交是通過了編譯和測(cè)試兩個(gè)環(huán)節(jié)的。
- 在發(fā)版前盒揉,項(xiàng)目經(jīng)理會(huì)在
production
分支上打一個(gè)tag
晋被,這個(gè)動(dòng)作會(huì)觸發(fā)release
環(huán)節(jié)的執(zhí)行,會(huì)把build目錄下的文件打包成一個(gè)帶有版本號(hào)的壓縮包刚盈,同時(shí)產(chǎn)生一個(gè)可下載的http鏈接羡洛,這樣做的好處也非常明顯,在服務(wù)器開發(fā)中藕漱,我覺得最大的好處是把開發(fā)和運(yùn)維解耦了欲侮,這兩個(gè)部門間再也不會(huì)扯皮了。
通過這三篇文章肋联,你應(yīng)該對(duì)git由淺入深的有了一些認(rèn)識(shí)威蕉,可以看到git對(duì)團(tuán)隊(duì)協(xié)作、團(tuán)隊(duì)成員間工作的透明性的威力很大橄仍,減少了噪音的同時(shí)韧涨,讓團(tuán)隊(duì)更專注于核心的代碼層面上,這也是git的作者Linus所提倡的:
Talk is cheap, read the f**king code.