git-flow 操作實踐
安裝
brew install git-flow
init
$ git flow init
Initialized empty Git repository in ~/project/.git/
No branches exist yet. Base branches must be created now.
Branch name for production releases: [master]
Branch name for "next release" development: [develop]
How to name your supporting branch prefixes?
Feature branches? [feature/]
Release branches? [release/]
Hotfix branches? [hotfix/]
Support branches? [support/]
Version tag prefix? []
這時會在當前目錄執(zhí)行git init操作. 并且生成4個分支名字, 并且默認在develop分支上, develop分支就是我們主要工作的地方.
$ git branch
* develop
master
我們除了要把master分支推到遠端倉庫, develop同樣也要推到遠端倉庫 git push origin develop
Feature branches
開始一個新功能添加, 或者是一般bug修復, 或者是其他功能. 我們需要開一個feature分支. 我們在本地的主要工作都是要開feature分支完成的. ** 不要在develop 分支上開發(fā). **
$ git flow feature start authentication
Switched to a new branch 'feature/authentication'
Summary of actions:
- A new branch 'feature/authentication' was created, based on 'develop'
- You are now on branch 'feature/authentication'
Now, start committing on your feature. When done, use:
git flow feature finish authentication
然后你可以做自己的修改了, 完成后, 需要將feature合并回develop分支.
$ git flow feature finish authentication
Switched to branch 'develop'
Updating 9060376..00bafe4
Fast-forward
authentication.txt | 1 +
1 file changed, 1 insertion(+)
create mode 100644 authentication.txt
Deleted branch feature/authentication (was 00bafe4).
Summary of actions:
- The feature branch 'feature/authentication' was merged into 'develop'
- Feature branch 'feature/authentication' has been removed
- You are now on branch 'develop'
多個開發(fā)者進行開發(fā)時, 會出現每個人本地的develop分支不一致的情況, 這樣在每次拉取遠端develop分支時, 會出現很多merge提交. 關于這個問題, 在最后的
減少以及消滅無用的merge commit
章節(jié)中說明.
releases
在沒有使用git-flow工具時, 發(fā)布是一件很繁瑣的事情, 要保留一個用于releases的分支, 打tag等. 使用git-flow可以用簡單命令解決.
$ git flow release start 0.1.0
Switched to a new branch 'release/0.1.0'
Summary of actions:
- A new branch 'release/0.1.0' was created, based on 'develop'
- You are now on branch 'release/0.1.0'
Follow-up actions:
- Bump the version number now!
- Start committing last-minute fixes in preparing your release
- When done, run:
git flow release finish '0.1.0'
你將開始一個發(fā)布, 一般可以直接finishi
$ git flow release finish 0.1.0
Switched to branch 'master'
Merge made by the 'recursive' strategy.
authentication.txt | 1 +
1 file changed, 1 insertion(+)
create mode 100644 authentication.txt
Deleted branch release/0.1.0 (was 1b26f7c).
Summary of actions:
- Latest objects have been fetched from 'origin'
- Release branch has been merged into 'master'
- The release was tagged '0.1.0'
- Release branch has been back-merged into 'develop'
- Release branch 'release/0.1.0' has been deleted
這時develop分支回合并到master分支, 并打tag. 之后我們只要把master和tag都推到遠端倉庫即可.
Hotfixing production code
緊急bug修復, 在已經發(fā)布的代碼上更正. 會從master開出hotfix分支, 然后合并回master, 也會合并回develop.
$ git flow hotfix start assets
Switched to a new branch 'hotfix/assets'
Summary of actions:
- A new branch 'hotfix/assets' was created, based on 'master'
- You are now on branch 'hotfix/assets'
Follow-up actions:
- Bump the version number now!
- Start committing your hot fixes
- When done, run:
git flow hotfix finish 'assets'
然后修改問題, 之后提交:
$ git flow hotfix finish assets
Switched to branch 'master'
Merge made by the 'recursive' strategy.
assets.txt | 1 +
1 file changed, 1 insertion(+)
create mode 100644 assets.txt
Switched to branch 'develop'
Merge made by the 'recursive' strategy.
assets.txt | 1 +
1 file changed, 1 insertion(+)
create mode 100644 assets.txt
Deleted branch hotfix/assets (was 08edb94).
Summary of actions:
- Latest objects have been fetched from 'origin'
- Hotfix branch has been merged into 'master'
- The hotfix was tagged '0.1.1'
- Hotfix branch has been back-merged into 'develop'
- Hotfix branch 'hotfix/assets' has been deleted
在往下閱讀之前, 你最好將以上的命令實踐一遍, 感受git-flow的操作與分支流向. 推薦SourceTree來跟蹤變化.
減少以及消滅無用的merge commit
如果是一個人使用git-flow, 你會發(fā)現你所有的commit以及commit log都是有意義的. 你所有的更改, feature合并都是有明確記錄的.
但是在多人使用下, 大家各自在本地開發(fā), 往develop分支上merge, 那么就會出現每個人的develop分支不一致. 那么當一個人把自己的develop分支push到遠端時, 其他人pull的時候就會出現分支合并, 產生 "Merge branch 'develop' of remote into develop" 的類似commit.
很多時候, 合并時沒有沖突, 自動完成. 這種merge產生的commit是沒有意義的, 而且會讓分支看起來混亂.
按照以下規(guī)則可以減少甚至消除這種無意義的commit:
- 本地在往develop分支進行合并時, **
先在develop上執(zhí)行git pull
**, 當你沒有在本地對develop分支有commit時, 執(zhí)行git pull
是會發(fā)生Fast-forward合并的, 這種默認并不產生commit. - 將feature合并到develop上.
- push develop. 將你的修改提交到遠端.
多數時候, 如果多個人分開執(zhí)行以上操作, 是不會有問題的.
如果多個人同時進行以上操作, 那么在進行第三步的時候, 是push不上去的, 需要先pull, 那么又會產生所謂的無意義commit, 該怎么辦呢:
這時不要用git pull
來拉取更改, 改為使用:
git pull --rebase
這個命令會將遠端代develop拉下來, 然后從本地develop上跟遠端develop分叉的地方開始, 將本地的commit一個個應用到遠端develop的末端, 使之成為一條直線, 從而沒有了merge commit.
關于沖突, rebase的時候也會有沖突:
比如遠端 a->b->c
你的 a->b->d
進行rebase之后 a->b->c->e
, 其中e
的更改內容和log就是你的d
, 如果有沖突, 沖突的修改也是提現在e
中
修改完沖突, 我們會進行commit提交沖突修改. 不要使用
git commit -m
, 請直接使用git commit
, git會識別你這是一個沖突提交.
當然, 操作的疏忽依然會產生無意義的commit, 但這并不致命, 注意就好.
如果真的要消滅無意義commit: 在你
git pull
之后發(fā)現自動合并了, 那么用git reset --hard [剛剛你本地的提交commit version]
進行本地版本回滾, 然后再git pull --rebase
我對rebase的理解也不是很多, 以上只是應用中的使用體會, 肯定還存在很多沒有想到的情況和處理不當的地方, 請大家多提出來指正, 共同討論.