今天新建項目的時候,發(fā)現(xiàn)rdc除原有的分支模式以外還增加了master分支開發(fā)模式和git flow模式,這是一件非常令人欣喜的事情——畢竟git flow是一個流傳已久的,大家都普遍接受的開發(fā)模式。
于是我就把應(yīng)用刪掉了,改用git flow模式,目前體驗很完美。
鑒于很多人可能還不太了解git flow,本文就對此分享一些微小的經(jīng)驗。
http://insights.thoughtworkers.org/gitflow-consider-harmful/
你會用git嗎?
我相信在座的大多數(shù)人都會自信的回答:“會”。
而實際上,大家可能從來沒有考慮過自己的用法是否真的科學(xué),真的健壯,尤其是項目越來越大,人數(shù)越來越多,周期越來越長的時候。
其中,典型的有以下幾個問題:
- 當(dāng)我開發(fā)某個功能到一半的時候,PM突然給我安排了一個新的緊急任務(wù),我該怎么開始這個任務(wù),而不影響現(xiàn)在的?
- 當(dāng)我代碼寫好了的時候,如何發(fā)布?
- 當(dāng)我發(fā)布后,代碼出問題了,如何快速修復(fù)?
- 以上的情況,還要求修復(fù)后,還要包含之后開發(fā)的所有代碼?
大部分開發(fā)人員使用git的時候,基本只使用兩個甚至一個分支,所以下面的這些理念,顯然是打開了一扇新世界的大門了。
方案
顯然,不光代碼有代碼規(guī)范,代碼的管理和協(xié)同同樣需要一個清晰的流程和規(guī)范,由此,行業(yè)內(nèi)的通用解決方案是Git Flow。

怎么樣,眼花繚亂吧,不過我可以給你個建議:把頭左轉(zhuǎn)90度,別著急罵....這是office picture,并非我畫的。
在上面這幅圖上,最上面的一行,代表分支,它們分別是
| 名稱 | 解釋 |
|---|---|
| master | 這個分支最近發(fā)布到生產(chǎn)環(huán)境的代碼,最近發(fā)布的Release, 這個分支只能從其他分支合并,不能在這個分支直接修改 |
| Develop | 這個分支是我們是我們的主開發(fā)分支,包含所有要發(fā)布到下一個Release的代碼,這個主要合并與其他分支,比如Feature分支 |
| Feature | 這個分支主要是用來開發(fā)一個新的功能,一旦開發(fā)完成,我們合并回Develop分支進(jìn)入下一個Release |
| Release | 當(dāng)你需要一個發(fā)布一個新Release的時候,我們基于Develop分支創(chuàng)建一個Release分支,完成Release后,我們合并到Master和Develop分支 |
| Hotfix | 當(dāng)我們在Production發(fā)現(xiàn)新的Bug時候,我們需要創(chuàng)建一個Hotfix, 完成Hotfix后,我們合并回Master和Develop分支,所以Hotfix的改動會進(jìn)入下一個Release. |
實現(xiàn)細(xì)則
master分支
在master分枝上工作,我們需要遵循一個基本原則,所有在master分支上的commit應(yīng)該tag.

feature分支
feature分支做完后,必須合并回develop分支, 合并完分支后一般會刪點這個feature分支,但是我們也可以保留

開始一個新的功能的開發(fā)
git checkout -b some-feature develop
# Optionally, push branch to origin:
git push -u origin some-feature
# 做一些改動
git status
git add some-file
git commit
開發(fā)完成
git pull origin develop
git checkout develop
git merge --no-ff some-feature
git push origin develop
git branch -d some-feature
# If you pushed branch to origin:
git push origin --delete some-feature
release分支
分支名 release/*
release分支基于develop分支創(chuàng)建,打完release分支后,我們可以在這個release分支上測試,修改bug等。同時,其它開發(fā)人員可以基于開發(fā)新的feature,一旦打了release分支之后不要從develop分支上合并新的改動到Release分支
發(fā)布release分支時,合并release到master和develop, 同時在master分支上打個tag記住release版本號,然后可以刪除release分支了(當(dāng)然,你可以選擇不刪除)。

開始release
git checkout -b release-0.1.0 develop
# Optional: Bump version number, commit
# Prepare release, commit
完成release
git checkout master
git merge --no-ff release-0.1.0
git push
git checkout develop
git merge --no-ff release-0.1.0
git push
git branch -d release-0.1.0
# If you pushed branch to origin:
git push origin --delete release-0.1.0
git tag -a v0.1.0 master
git push --tags
hotfix
分支名 hotfix/*
hotfix分支基于master分支創(chuàng)建,開發(fā)完后需要合并回master和develop分支,同時在master上打一個tag

開始hotfix
git checkout -b hotfix-0.1.1 master
完成hotfix
git checkout master
git merge --no-ff hotfix-0.1.1
git push
git checkout develop
git merge --no-ff hotfix-0.1.1
git push
git branch -d hotfix-0.1.1
git tag -a v0.1.1 master
git push --tags
工具
如果你能堅持看到這里,我真的為你感到欣喜,這說明你是用心學(xué)習(xí)的,并且是不畏艱險的,畢竟上面那么長的一大串的代碼,可能已經(jīng)使你感到畏懼。
而顯然的是,作為通用的一個解決方案,不可能這么繁瑣,那么,唯一的可能是——有!工!具!
| 平臺 | 命令 | |
|---|---|---|
| OS X | brew install git-flow | |
| Linux | apt-get install git-flow | |
| Windows | wget -q -O - --no-check-certificate https://github.com/nvie/gitflow/raw/develop/contrib/gitflow-installer.sh | bash |
| IDEA | Git Flow Integration |
其中還有一大部分是gui的,比較簡單,本文就不再贅述了。下面著重介紹下命令行下的使用
- 初始化: git flow init
- 開始新Feature: git flow feature start MYFEATURE
- Publish一個Feature(也就是push到遠(yuǎn)程): git flow feature publish MYFEATURE
- 獲取Publish的Feature: git flow feature pull origin MYFEATURE
- 完成一個Feature: git flow feature finish MYFEATURE
- 開始一個Release: git flow release start RELEASE [BASE]
- Publish一個Release: git flow release publish RELEASE
- 發(fā)布Release: git flow release finish RELEASE
別忘了git push --tags - 開始一個Hotfix: git flow hotfix start VERSION [BASENAME]
- 發(fā)布一個Hotfix git flow hotfix finish VERSION
仔細(xì)觀察,這些命令都是有規(guī)矩的,它們大概可以如下圖表示

###################################################################
基礎(chǔ)語法
git init 把工作區(qū)變?yōu)橐粋€git可以管理的倉庫
(1)git add 跟蹤要修改的文件(把文件add到了緩存區(qū))
(2)git commit 提交文件到版本庫(把緩存區(qū)的文件提交到了當(dāng)前分支)
(3)git status 查看修改過的文件的狀態(tài)(已跟蹤,未跟蹤,已提交,未提交)
(4)git log 查看提交的log(最上邊兒是最近一次提交的)
顯示了:commit_id,auther,commit_date,修改的內(nèi)容
(5)git reset —head HEAD^ 撤回上一個版本
(6)cat 查看當(dāng)前文件內(nèi)容
(7)git reset --hard 3628164 后悔撤回了的那個版本的話執(zhí)行這個回退到那個版本 3628164是那個版本的版本號(commit_id)
(8)git reflog 查看命令歷史
(9)暫存區(qū)和工作區(qū)的區(qū)別
工作區(qū):我們正常工作的目錄項目根目錄下(.git目錄就在工作區(qū),它不是工作區(qū)而是git的版本庫)
暫存區(qū):存在版本庫.git里,通常稱為stage,在git init時會為我們創(chuàng)建第一個分支master,以及指向master的指針HEAE
?:如果修改的文件沒有被add倒暫存區(qū),commit的時候?qū)⒉粫惶峤坏疆?dāng)前分支(因為git跟蹤并管理的是修改而不是文件本身)
(10)git checkout — file (撤回沒有add到暫存區(qū)的已經(jīng)修改的文件)
(11)git reset HEAD file (撤回已經(jīng)add到暫存區(qū)但是還沒有commit的文件,撤回到了工作區(qū),如果還想還原的話執(zhí)行checkout命令)
(12)刪除文件的時候一定要注意 :(刪除的是已經(jīng)commit 到分支的文件)
?:切記不要執(zhí)行rm file命令,如果實在執(zhí)行了,可以通過checkout 撤回工作區(qū)的修改應(yīng)為刪除工作區(qū)的文件也是對工作區(qū)文件的修改所以可以通過checkout撤回修改
?:刪除的時候執(zhí)行g(shù)it rm file這時候暫存區(qū)文件也給刪除了,執(zhí)行commit提交就行了
?:如果是刪除沒有commit到分支的文件看情況執(zhí)行rm file或者git rm file
(13)遠(yuǎn)程倉庫
git remote add origin https://github.com/easonlovejiven/learngit.git 關(guān)聯(lián)一個遠(yuǎn)程倉庫
關(guān)聯(lián)之后推送最新的code
git push origin 本地工作分支 (把當(dāng)前分支推送到遠(yuǎn)程)
?:第一推送時遠(yuǎn)程是空的所以要加-u參數(shù)(git push -u origin 本地工作分支)
(14)分支管理
創(chuàng)建合并分支:
git checkout -b dev 創(chuàng)建并切換到dev分支,相當(dāng)于:git branch dev ,git checkout dev
git branch 列出本地所有分支
git checkout 分支名 切換分支
git merge 分支名 合并分支
git branch -d 分支名 合并之后就可以刪除新建的開發(fā)分支了
?:新建的分支默認(rèn)和本地master分支一樣的內(nèi)容
解決分支沖突:
both modified :文件的這個狀態(tài)證明有沖突了
當(dāng)merge出現(xiàn)沖突時git無法自動合并,必須手動的修改沖突的文件(merge后修改)修改成要merge的那個分支,修改完后刪除要merge的那個分支,然后add,commit提交
git log —graph 查看分支合并圖
(15)bug分支
如果要修復(fù)bug時,需要建立專門的bug分支來修復(fù),然后合并,最后刪除
git stash:存儲當(dāng)前(dev)分支的工作現(xiàn)場(去處理其它分支的事情)
git stash pop:其它分支處理完了,切換到dev分支,恢復(fù)之前未完成的工作內(nèi)容
(16)遠(yuǎn)程倉庫
遠(yuǎn)程倉庫的默認(rèn)名稱是origin
git remote :查看遠(yuǎn)程分支的名稱
git branch origin 本地分支
git pull :更新遠(yuǎn)程分支最新的修改到本地
(17)標(biāo)簽管理
撤回上次提交
git reset HEAD^
如果刪除了一個已經(jīng)push的本地的分支想要恢復(fù)的話,運(yùn)行g(shù)it br -a看下遠(yuǎn)程分支紀(jì)錄然后運(yùn)行g(shù)it co remotes/origin/T183-2 恢復(fù)分支
高級語法
使遠(yuǎn)程庫強(qiáng)制覆蓋本地代碼(git pull時出現(xiàn)沖突 放棄本地修改)
git fetch --all 只是下載代碼到本地,不進(jìn)行合并操作
git reset --hard origin/master 把HEAD指向最新下載的版本
本地版本強(qiáng)制覆蓋遠(yuǎn)程版本
git push --force origin
git index.lock鎖定文件
rm -f ./.git/index.lock
在你進(jìn)行某些比較費(fèi)時的git操作時自動生成,操作結(jié)束后自動刪除,相當(dāng)于一個鎖定文件,目的在于防止對一個目錄同時進(jìn)行多個操作。有時強(qiáng)制關(guān)閉進(jìn)行中的git操作,這個文件沒有被自動刪除,之后你就無法進(jìn)行其他操作,必須手動刪除
git Please move or remove them before you can merge
這是因為本地有修改,與云端別人提交的修改沖突,又沒有merge。如果確定使用云端的代碼,最方便的解決方法是刪除本地修改
git clean -d -fx ""
d -----刪除未被添加到git的路徑中的文件
f -----強(qiáng)制運(yùn)行
x -----刪除忽略文件已經(jīng)對git來說不識別的文件
常用語法
git pull 等價于 git fetch + git merge
git fetch不會執(zhí)行自動merge
git pull 和 git pull origin master 和 git pull origin 區(qū)別
在git clone的時候,所有本地分支默認(rèn)與遠(yuǎn)程主機(jī)的同名分支,建立追蹤關(guān)系,也就是說,本地的master分支自動"追蹤"origin/master分支
遠(yuǎn)程分支是與當(dāng)前分支合并
git pull origin master
如果當(dāng)前分支與遠(yuǎn)程分支存在追蹤關(guān)系,git pull就可以省略遠(yuǎn)程分支名。
git pull origin
如果當(dāng)前分支只有一個追蹤分支,連遠(yuǎn)程主機(jī)名都可以省略
git pull