本文會(huì)分為兩部分講解,第一部分介紹Git的基礎(chǔ)概念、常見客戶端、常用命令,是一個(gè)基礎(chǔ)說明。第二部分介紹Git的管理流程,主要是GitFlow,Github Flow,Gitlab Flow和ExeFlow四種。
Git相關(guān)
基本概念
Git是一個(gè)基于GNU協(xié)議的開源分布式版本控制系統(tǒng),是由Linux的創(chuàng)始人Linus Torvalds在2005為了進(jìn)行Linux內(nèi)核的研發(fā)時(shí)自己編寫的。不同于之前的大部分客戶端-服務(wù)器模式的代碼管理系統(tǒng),在每臺(tái)電腦上的每個(gè)Git目錄都是一個(gè)完整的代碼倉(cāng)庫(kù),包含了歷史所有的提交記錄并且可以完整查看所有版本,而不需要有服務(wù)器或者網(wǎng)絡(luò)連接。
2019年9月Git的當(dāng)前的最新版本為2.23.0.
常見客戶端
TortoiseGit

TortoiseGit,就是我們俗稱小烏龜。他們?yōu)镾vn也提供了很優(yōu)秀的windows客戶端。而且這是一個(gè)開源的軟件,當(dāng)前最新的版本位2.8.0 。
安裝之后會(huì)自動(dòng)注入系統(tǒng)的右鍵菜單,在任何路徑右擊之后都會(huì)出現(xiàn)

如圖的選項(xiàng),這是在非git倉(cāng)庫(kù)時(shí)。當(dāng)在git倉(cāng)庫(kù)右鍵點(diǎn)擊時(shí)完整菜單如下

查看提交記錄

Sourcetree

Sourcetree是Atlassian提供的一款免費(fèi)的Git客戶端工具,目前的版本是3.2.6。
安裝之后直接打開客戶端使用,整體界面大致如圖。

Intellij Idea

Idea是Java開發(fā)非常熱門的IDE,其中也集成了多種SCM工具,自然也包括Git的客戶端,整體的使用感受還是不錯(cuò)的。

命令行
最后名不符實(shí)的再加上一個(gè)命令行吧,有很多同學(xué)還是習(xí)慣手敲命令的。

常用命令
存儲(chǔ)區(qū)域
Git主要有四塊存儲(chǔ)區(qū)域:
Workspace:工作區(qū)
Index / Stage:暫存區(qū)
Repository:倉(cāng)庫(kù)區(qū)(或本地倉(cāng)庫(kù))
Remote:遠(yuǎn)程倉(cāng)庫(kù)
工作區(qū)是本地計(jì)算機(jī)存儲(chǔ),平時(shí)項(xiàng)目代碼存儲(chǔ)的地方。
暫存區(qū)也是在本地存儲(chǔ),當(dāng)你在修改代碼但是還沒有執(zhí)行commit操作時(shí)臨時(shí)存放你的改動(dòng),事實(shí)上它只是一個(gè)文件,保存即將提交到文件列表信息。
倉(cāng)庫(kù)區(qū)就是本地版本庫(kù),這里面有你提交到所有版本的數(shù)據(jù)。其中HEAD指向最新放入倉(cāng)庫(kù)的版本。
遠(yuǎn)程倉(cāng)庫(kù)就是比如Gitlab或者Github等。
幾個(gè)存儲(chǔ)區(qū)域之間的工作流程一般是這樣:

還有另外一個(gè)版本的流程:

命令之 add & commit &push

add & commit 實(shí)際上就是一個(gè)文件加入版本控制的過程,在受git管理的目錄下新建一個(gè)文件,首先要將它標(biāo)記為add,接下來commit到本地的倉(cāng)庫(kù),就完成了本地的版本管理。
之后可以選擇是否執(zhí)行push操作,如果執(zhí)行就是將本地的變更提交到遠(yuǎn)程服務(wù)器上,這樣別人就可以獲取到你的更新了。
命令之 branch & checkout
branch是常見的創(chuàng)建分支應(yīng)用的語法,git和傳統(tǒng)的cs模式的SCM的工具相比branch的代價(jià)是非常小的,影響也是非常小的。git的branch可以只存在與本地,輕易和合并與刪除。

上圖就是很多Flow流程中可能存在的多個(gè)分支(實(shí)際上這些分支本地和遠(yuǎn)程都是存在的)。
我們本地的一個(gè)項(xiàng)目可能就會(huì)存在多個(gè)分支,我們使用checkout命令,簽出一個(gè)分支之后,環(huán)境中的文件都會(huì)變?yōu)樵摲种У南嚓P(guān)文件。
命令之 cherry-pick
pick是挑選的意思,我們看一下示意圖

這是要求將 bugFix 分支上的 C3 、side 分支上的 C4 以及another分支上的C7通過cherry-pick的形式拿到 master分支上。這是很典型的一個(gè)使用cherry-pick的場(chǎng)景,bug修復(fù)的合并。
命令之 merge & rebase
通過上面的branch和push,我們已經(jīng)切出不同的分支并且提交了,接下來就是要合并我們的提交內(nèi)容到主分支上,這時(shí)我們可能會(huì)面臨兩個(gè)命令選擇 merge和rebase。
這兩個(gè)命令有什么區(qū)別呢?我們通過一個(gè)模擬界面來看一下:
使用merge命令

使用rebase命令

建議:
rebase會(huì)把你當(dāng)前分支的 commit 放到公共分支的最后面,所以叫變基。就好像你從公共分支又重新拉出來這個(gè)分支一樣。
merge 會(huì)把公共分支和你當(dāng)前的commit 合并在一起,形成一個(gè)新的 commit 提交。
為什么建議使用rebase,因?yàn)橥ǔN覀兪莊eature分支基于master分支進(jìn)行rebase,master是長(zhǎng)期固定分支,feature是臨時(shí)分支,我們不希望因?yàn)榕R時(shí)分支的變更影響到master分支的提交記錄,而且通常情況下master分支是鎖定不允許直接提交的。所以建議大家使用rebase,這樣能夠在不影響master分支的情況下還能夠合并最新的內(nèi)容。
Flow相關(guān)
我們這里主要講四種flow進(jìn)行對(duì)比,GitFlow,GitHub Flow,GitLab Flow,ExeFlow。
我對(duì)于項(xiàng)目管理的核心理解有兩點(diǎn):
需求邊界
時(shí)間邊界
也就是一次迭代,就是在規(guī)定的時(shí)間邊界與規(guī)定的需求邊界范圍內(nèi)完成。如果兩方面都能夠保質(zhì)保量,自然沒有問題。其實(shí)那種Flow我覺得差異不算很大。但是當(dāng)其中有一點(diǎn)無法滿足時(shí),不同的Flow能夠達(dá)到的效果就不同了。這點(diǎn)自然是不同的企業(yè)有不同的場(chǎng)景與要求,有的企業(yè)可以拖延時(shí)間(工期),但是一定要保證規(guī)劃內(nèi)的需求全部開發(fā)測(cè)試完成。有的公司則是對(duì)時(shí)間節(jié)點(diǎn)的要求更高,可以減少某些需求,但是一定要在規(guī)定時(shí)間點(diǎn)發(fā)布上線。我們?cè)诶斫饷糠Nflow時(shí),也會(huì)對(duì)項(xiàng)目管理的兩點(diǎn)影響說明一下。
GitFlow
GitFlow來源應(yīng)該是 Vincent Driessen 在2010年1月發(fā)表的這篇《A successful Git branching model》,基本是現(xiàn)在Git中最出名的流程管理方法了。

我整理了其對(duì)應(yīng)的流程圖,其中加粗的是指長(zhǎng)期分支。可以看到master和develop是其中的長(zhǎng)期分支,對(duì)外的發(fā)布基于master分支,對(duì)內(nèi)的研發(fā)基于develop分支。需要發(fā)布版本時(shí),是從develop分支切出release分支,最終合并至master。所以我理解在GitFlow中,最重要的實(shí)際上是develop分支,它承載了實(shí)際功能的開發(fā)修正和發(fā)布,而master最大的作用有兩個(gè),一是發(fā)布,二是熱修正(hotfix)。
GitFlow的流程我理解時(shí)偏重時(shí)間,而非需求的。也就是說如果臨近發(fā)布時(shí)間,而需求沒有完成,其唯一的選擇就是延期,因?yàn)榘凑樟鞒蹋瑀elease分支是從develop分支切出,如果測(cè)試的環(huán)境是基于develop,很可能是沒有打到發(fā)布標(biāo)準(zhǔn)的,所以只能等打到發(fā)布標(biāo)準(zhǔn)后才能進(jìn)行后續(xù)步驟。但是好處在于開發(fā)只用基于develop分支,很難出現(xiàn)漏合并代碼或者bug修正之類的情況。我也覺得這份流程在大型企業(yè)內(nèi)部是比較難推進(jìn)的,因?yàn)樗沫h(huán)境管理還不夠,它的release、master分別對(duì)應(yīng)預(yù)發(fā)布和正式環(huán)境,develop我覺得還不夠清晰,因?yàn)檫@塊我們通常是需要兩個(gè)環(huán)境,開發(fā)和測(cè)試環(huán)境。所以對(duì)于多環(huán)境管理我覺得是需要根據(jù)不同的企業(yè)的要求進(jìn)行改造的。
GitHub Flow
顧名思義,GitHub Flow就是GitHub推薦的管理流程

可以看到,只能用簡(jiǎn)單2字形容,只有master和feature兩個(gè)分支概念,其中master是長(zhǎng)期分支。所以我還加上了Github官方的一些說明。
我覺得這不是一份可以用于企業(yè)級(jí)復(fù)雜項(xiàng)目管控的Git 流程,最基礎(chǔ)的就是沒有多環(huán)境管理,無法想象多角色配合時(shí)只基于master分支如何進(jìn)行。master究竟用于測(cè)試環(huán)境還是隨時(shí)可發(fā)布的正式環(huán)境呢?其次這份流程應(yīng)該也是偏重于需求而非時(shí)間。理由和GitFlow一樣。
我覺得GitHub推出的這份flow主要是應(yīng)用于其平臺(tái)上大部分托管的小型開源項(xiàng)目,并且盡量結(jié)合平臺(tái)提供的其他組件。對(duì)于企業(yè)內(nèi)部不夠合適。
GitLab Flow
GitLab Flow自然是基于GitLab環(huán)境的flow管理流程

這個(gè)Flow實(shí)際上最核心的分支是基于master,生產(chǎn)環(huán)境是production,預(yù)發(fā)布環(huán)境是pre-production。我覺得對(duì)于多環(huán)境的問題實(shí)際上和GitFlow很相似,也是開發(fā)和測(cè)試環(huán)境不夠清晰。
提交、審核基于GitLab的MR進(jìn)行。截圖的部分就是GitLab官方的MR的說明。
GitLab Flow與GitFlow的差別我覺得僅僅在于master與develop的分支命名,還有就是加入了MR(但是由于GitFlow不基于任何服務(wù)端環(huán)境,所以這塊是可以整合的),問題也很相似。
ExeFlow
由于上面幾種Flow在時(shí)間和需求都是選擇了需求而延遲了時(shí)間,我也順便講一下選擇時(shí)間而放棄一些需求的Flow流程吧。
這是我之前一家公司的流程設(shè)計(jì),服務(wù)端是GitLab。
實(shí)際工作場(chǎng)景:
我們的系統(tǒng)由于主要是面向大型企業(yè)內(nèi)部使用,存在復(fù)雜的分發(fā)流程和權(quán)限控制,經(jīng)過長(zhǎng)時(shí)間的累積業(yè)務(wù)模型也很復(fù)雜各種關(guān)聯(lián)和引用,所以有一些大型任務(wù)的開發(fā)周期可能會(huì)比較長(zhǎng),到達(dá)2-3個(gè)月的周期。
我們的迭代周期正常是1個(gè)月。流程大概如下:
上月末進(jìn)行迭代計(jì)劃評(píng)估與安排,這里會(huì)確認(rèn)下月迭代目標(biāo)的Story內(nèi)容與數(shù)據(jù)。各自主管進(jìn)行子任務(wù)的拆分評(píng)估與排期。
開發(fā)時(shí)間一般是2周,我們基本是會(huì)在月中設(shè)定研發(fā)截止線,所有研發(fā)任務(wù)要在截止線前完成提測(cè)。期間有完成的任務(wù)可以隨時(shí)提測(cè)?!旧婕胺种В篎eature,Local,Develop】
完整的系統(tǒng)集成測(cè)試時(shí)間一般是安排在第三周,測(cè)試會(huì)進(jìn)行全面的測(cè)試。本周研發(fā)的主要任務(wù)一方面是處理Bug,一方面可以介入下月迭代大項(xiàng)的需求說明與分析。【涉及分支:Feature,Local,Develop】
第四周的前三天,我們會(huì)切出預(yù)發(fā)布的分支在第四周周一時(shí),會(huì)給出明確本次能夠上線的Story List,不在清單內(nèi)的都不允許合并只預(yù)發(fā)布環(huán)境(也就是我們實(shí)際上運(yùn)行需求在預(yù)發(fā)布之前仍舊有變更,只要測(cè)試人員通過了集成測(cè)試環(huán)境,就可以合并并且發(fā)布),本次發(fā)版的具體內(nèi)容和通知也是當(dāng)天發(fā)出?!旧婕胺种В篎eature,Release】
發(fā)版一般安排在當(dāng)月的最后一個(gè)周四(為了防止有線上問題,所以不能是周五第二天會(huì)沒有人員值守)?!旧婕胺种В篟elease,Master】
流程圖:

這里有幾個(gè)特點(diǎn):
develop對(duì)于測(cè)試環(huán)境,local對(duì)應(yīng)開發(fā)聯(lián)調(diào)環(huán)境。
所有的分支起始時(shí)都是由master分支切出
固定長(zhǎng)期分支有三個(gè):master,develop,local
所有的分支不能直接向master提交,必須通過release驗(yàn)證后合并至master。
master分支鎖定需要權(quán)限審核提交
release是臨時(shí)分支,指定時(shí)間從master切出,直接從feature合并。
先來說說有點(diǎn),根據(jù)之前提供的流程來看,我們企業(yè)要求的是時(shí)間保障而需求可以調(diào)整。所以在指定時(shí)間節(jié)點(diǎn)到來時(shí),我們會(huì)確定一份可以發(fā)布的需求清單,根據(jù)這份清單來合并至release,從而最終能夠發(fā)布。這是一個(gè)比較典型的保時(shí)間點(diǎn),放需求的流程管理。
但是這個(gè)會(huì)有下面幾個(gè)問題:
develop和local分支從master切出后,長(zhǎng)期和master不同步,所以需要定期的rebase,否則會(huì)產(chǎn)生很多環(huán)境不一致導(dǎo)致的問題。
hotfix或者feature提交之后的bug修正,都是需要提交最多三個(gè)分支的。研發(fā)人員的操作會(huì)非常復(fù)雜。
但是由于這個(gè)流程解決了我們實(shí)際生產(chǎn)流程中的問題,所以整體在控制和配合上帶來的收益遠(yuǎn)大于我們的障礙。所以這套流程還是長(zhǎng)期推廣了起來。
總結(jié)
Git是一個(gè)工具,F(xiàn)low是一套管理流程。最重要的并不是我們?cè)谟檬裁?,而是我們解決了什么問題?我們?cè)噲D解決的問題到底是不是真實(shí)的問題,還是我們一廂情愿臆想出來的。整個(gè)過程,實(shí)際上是我們針對(duì)企業(yè)的環(huán)境和問題進(jìn)行發(fā)掘的解決的過程,而不是單純挑選工具和流程的過程。
記得先問自己,我現(xiàn)在到底要解決的是什么問題?