分支說明和對應(yīng)的操作
master分支
Git主分支的名字,默認(rèn)叫做master。它是自動建立的,版本庫初始化以后,默認(rèn)就是在主分支在進(jìn)行開發(fā)。
主分支,永遠(yuǎn)處于穩(wěn)定狀態(tài),對應(yīng)當(dāng)前線上版本。
以tag標(biāo)記一個版本,因此在master分支上看到的每一個tag都應(yīng)該對應(yīng)一個線上版本。
-
不允許在該分支直接提交代碼。
示意圖
dev分支
開發(fā)分支,包含了項目最新的功能和代碼,所有開發(fā)都依賴dev分支進(jìn)行。
可以用來生成代碼的最新隔夜版本(nightly)。如果想正式對外發(fā)布,就在master分支上,對dev分支進(jìn)行"合并"(merge)。
小的改動可以直接在dev分支進(jìn)行,改動較多時應(yīng)該切出新的feature分支進(jìn)行。
注:更好的做法是dev分支作為開發(fā)的主分支,也不允許直接提交代碼。小改動也應(yīng)該以feature分支提merge request合并,目的是保證每個改動都經(jīng)過了強制代碼review,降低代碼風(fēng)險。暫時不啟用這個方式。

Git創(chuàng)建dev分支的命令:
git checkout -b dev master
將dev分支發(fā)布到master分支的命令:
# 切換到Master分支
git checkout master
# 對dev分支進(jìn)行合并
git merge --no-ff dev
--no-ff參數(shù):默認(rèn)情況下,Git執(zhí)行"快進(jìn)式合并"(fast-farward merge),會直接將Master分支指向Develop分支。

使用--no-ff參數(shù)后,會執(zhí)行正常合并,在Master分支上生成一個新節(jié)點。

feature分支
功能分支,開發(fā)新功能的分支。
開發(fā)新的功能或者改動較大的調(diào)整,從develop分支切換出feature分支,分支名稱為feature-xxx。
開發(fā)完成后合并回develop分支并且刪除該feature-xxx分支。

功能分支的名字,可以采用feature-*的形式命名。
創(chuàng)建一個功能分支:
git checkout -b feature-x dev
開發(fā)完成后,將功能分支合并到dev分支:
git checkout dev
git merge --no-ff feature-xxx
刪除feature分支:
git branch -d feature-xxx
release分支
發(fā)布分支,新功能合并到dev分支,準(zhǔn)備發(fā)布新版本時使用的分支。預(yù)發(fā)布分支是從dev分支上面分出來的,預(yù)發(fā)布結(jié)束以后,必須合并進(jìn)dev和master分支。
當(dāng)dev分支完成功能合并和部分bug fix,準(zhǔn)備發(fā)布新版本時,切出一個release分支,來做發(fā)布前的準(zhǔn)備,分支名約定為release-*。
發(fā)布之前發(fā)現(xiàn)的bug就直接在這個分支上修復(fù),確定準(zhǔn)備發(fā)版本就合并到master分支,完成發(fā)布,同時合并到dev分支。
創(chuàng)建一個預(yù)發(fā)布分支:
git checkout -b release-1.2 dev
確認(rèn)沒有問題后,合并到master分支:
git checkout master
git merge --no-ff release-1.2
# 對合并生成的新節(jié)點,做一個標(biāo)簽
git tag -a 1.2
再合并到dev分支:
git checkout dev
git merge --no-ff release-1.2
最后,刪除預(yù)發(fā)布分支:
git branch -d release-1.2
fixbug分支,緊急修復(fù)bug分支
緊急修復(fù)線上bug分支
當(dāng)線上版本出現(xiàn)bug時,從master分支切出一個fixbug-分支,完成bug修復(fù),然后將fixbug-合并到master和dev分支(如果此時存在release分支,則應(yīng)該合并到release分支),合并完成后刪除該fixbug-*分支。
注意:以上就是在項目中應(yīng)該出現(xiàn)的分支以及每個分支功能的說明。其中穩(wěn)定長期存在的分支只有master和dev分支,別的分支在完成對應(yīng)的使命之后都會合并到這兩個分支然后被刪除。

創(chuàng)建一個修補bug分支:
git checkout -b fixbug-0.1 master
修補結(jié)束后,合并到master分支:
git checkout master
git merge --no-ff fixbug-0.1
git tag -a 0.1.1
再合并到develop分支:
git checkout develop
git merge --no-ff fixbug-0.1
最后,刪除"修補bug分支":
git branch -d fixbug-0.1
總結(jié):
- master: 線上穩(wěn)定版本分支。
- dev: 開發(fā)分支,衍生出feature分支和release分支。
- release: 發(fā)布分支,準(zhǔn)備待發(fā)布版本的分支,存在多個,版本發(fā)布之后刪除。
- feature: 功能分支,完成特定功能開發(fā)的分支,存在多個,功能合并之后刪除。
- fixbug: 緊急熱修復(fù)分支,存在多個,緊急版本發(fā)布之后刪除。
項目中分支操作流程示例
1、切到dev分支,更新dev最新代碼。
git checkout develop
git pull --rebase
2、新建feature分支,開發(fā)新功能
git checkout -b feature-xxx
git add <files>
git commit -m "feat(xxx): commit a"
git commit -m "feat(xxx): commit b"
# 其他提交
如果此時dev分支有一筆提交,影響到你的feature開發(fā),可以rebase dev分支,前提是該feature分支只有你自己一個在開發(fā),如果多人都在該分支,需要進(jìn)行協(xié)調(diào):
# 切換到dev分支并更新dev分支代碼
git checkout dev
git pull --rebase
# 切回 feature 分支
git checkout feature-xxx
git rebase develop
# 如果需要提交到遠(yuǎn)端,且之前已經(jīng)提交到遠(yuǎn)端,此時需要強推(強推需慎重!)
git push --force
3、完成feature分支,合并到dev分支
# 切到dev分支,更新下代碼
git check dev
git pull --rebase
# 合并feature分支
git merge feature-xxx --no-ff
# 刪除feature分支
git branch -d feature-xxx
# 推到遠(yuǎn)端
git push origin dev
4、當(dāng)某個版本所有的feature分支均合并到dev分支,就可以切出release分支,準(zhǔn)備發(fā)布新版本,提交測試并進(jìn)行bug fix
# 當(dāng)前在dev分支
git checkout -b release-xxx
# 在 release-xxx 分支進(jìn)行 bug fix
git commit -m "fix(xxx): xxxxx"
5、所有 bug 修復(fù)完成,準(zhǔn)備發(fā)布新版本
# master分支合并release分支并添加tag
git checkout master
git merge --no-ff release-xxx --no-ff
# 添加版本標(biāo)記,這里可以使用版本發(fā)布日期或者具體的版本號
git tag 1.0.0
# dev分支合并release分支
git checkout dev
git merge --no-ff release/xxx
# 刪除 release 分支
git branch -d release/xxx
至此,一個新版本發(fā)布完成。
6、線上出現(xiàn) bug,需要緊急發(fā)布修復(fù)版本
# 當(dāng)前在master分支
git checkout master
# 切出fixbug分支
git checkout -b fixbug-xxx
... 進(jìn)行bug fix提交
# master分支合并fixbug分支并添加tag(緊急版本)
git checkout master
git merge --no-ff hotfix/xxx --no-ff
# 添加版本標(biāo)記,這里可以使用版本發(fā)布日期或者具體的版本號
git tag 1.0.1
# dev分支合并fixbug分支(如果此時存在release分支的話,應(yīng)當(dāng)合并到release分支)
git checkout develop
git merge --no-ff fixbug-xxx
# 刪除fixbug分支
git branch -d hotfix-xxx
至此,緊急版本發(fā)布完成。
提交信息規(guī)范
git commit 格式如下:
<type>(<scope>): <subject>
具體格式:
<type>: <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
type: 本次commit的類型,諸如bugfix docs style等
scope: 本次 commit 波及的范圍
subject: 簡明扼要的闡述下本次 commit 的主旨,1.使用祈使句;2.首字母不要大寫;3.結(jié)尾無需添加標(biāo)點;
body: 同樣使用祈使句,在主體內(nèi)容中我們需要把本次commit詳細(xì)的描述一下,比如此次變更的動機,如需換行,則使用 |
footer: 描述下與之關(guān)聯(lián)的issue或break change
各個部分的說明如下:
- type 類型,提交的類別
- feat: 新功能
- fix: 修復(fù) bug
- docs: 文檔變動
- style: 格式調(diào)整,對代碼實際運行沒有改動,例如添加空行、格式化等
- refactor: bug 修復(fù)和添加新功能之外的代碼改動
- perf: 提升性能的改動
- test: 添加或修正測試代碼
- chore: 構(gòu)建過程或輔助工具和庫(如文檔生成)的更改
- scope 修改范圍
- 主要是這次修改涉及到的部分,簡單概括,例如 login、iap、search
- subject 修改的描述
- 具體的修改描述信息
Commit messages格式要求
# 標(biāo)題行:50個字符以內(nèi),描述主要變更內(nèi)容
#
# 主體內(nèi)容:更詳細(xì)的說明文本,建議72個字符以內(nèi)。 需要描述的信息包括:
#
# * 為什么這個變更是必須的? 它可能是用來修復(fù)一個bug,增加一個feature,提升性能、可靠性、穩(wěn)定性等等
# * 他如何解決這個問題? 具體描述解決問題的步驟
# * 是否存在副作用、風(fēng)險?
#
# 如果需要的化可以添加一個鏈接到issue地址或者其它文檔
范例:
feat(home): 首頁新功能
fix(login): 登錄錯誤處理
test(search): 搜索邏輯添加測試代碼
提交信息規(guī)范說明:
type + scope 能夠控制每筆提交改動的文件盡可能少且集中,避免一次很多文件改動或者多個改動合成一筆。
subject 使用中文,方便檢索和閱讀。
避免重復(fù)的提交信息,如果發(fā)現(xiàn)上一筆提交沒改完整,可以使用 git commit --amend 指令追加改動,盡量避免重復(fù)的提交信息。
分支之間操作的注意事項
- 同一分支git pull使用rebase
首先看一張圖:

想從中看出一條清晰的提交線幾乎是不可能的,充滿了 Merge remote-tracking branch 'origin/xxx' into xxx 這樣的提交記錄,同時也將提交線弄成了交錯縱橫的圖,沒有了可讀性。
這里最大的原因就是因為默認(rèn)的 git pull 使用的是 merge 行為,當(dāng)你更新代碼時,如果本地存在未推送到遠(yuǎn)程的提交,就會產(chǎn)生一個這樣的 merge 提交記錄。因此在同一個分支上更新代碼時推薦使用 git pull --rebase。
下面這張圖展示了默認(rèn)的 git pull 和 git pull --rebase 的結(jié)果差異,使用 git pull --rebase 目的是修整提交線圖,使其形成一條直線。

默認(rèn)的 git pull 行為是 merge,可以進(jìn)行如下設(shè)置修改默認(rèn)的 git pull 行為:
# 為某個分支單獨設(shè)置,這里是設(shè)置 dev 分支
git config branch.dev.rebase true
# 全局設(shè)置,所有的分支 git pull 均使用 --rebase
git config --global pull.rebase true
git config --global branch.autoSetupRebase always
使用 git pull --rebase 操作是比較好的,能夠得到一條很清晰的提交直線圖,方便查看提交記錄和 code review,但是由于 rebase 會改變提交歷史,也存在一些不好的影響。
- 分支合并使用 --no-ff
# 例如當(dāng)前在 develop 分支,需要合并 feature/xxx 分支
git merge --no-ff feature/xxx
--no-ff feature 含義:
先解釋下Git中的fast-forward:舉例來說,開發(fā)一直在dev分支進(jìn)行,此時有個新功能需要開發(fā),新建一個feature-a分支,并在其上進(jìn)行一系列開發(fā)和提交。
當(dāng)完成功能開發(fā)時,此時回到dev分支,此時develop分支在創(chuàng)建feature-a分支之后沒有產(chǎn)生任何的commit,那么此時的合并就叫做fast-forward。
fast-forward 合并的結(jié)果如下圖所示:

這種merge的結(jié)果就是一條直線了,無法明確看到切出一個新的feature分支,并完成了一個新的功能開發(fā)。
因此此時比較推薦使用git merge --no-ff,得到的結(jié)果就很明確知道,新的一系列提交是完成了一個新的功能,如果需要對這個功能進(jìn)行code review,那么只需要檢視叉的那條線上的提交即可。
