本文是我使用 Git 一段時間和看過一些資料後的總結,以及我的看法,深感 Git 的規範使用很是重要,不規範的使用會帶來不少麻煩。html
Gitflow 爲不一樣的分支分配一個很明確的角色,並定義分支之間如何和何時進行交互。分別有歷史分支、功能分支、發佈分支和維護分支。git
使用兩個分支來記錄項目的歷史。 master
分支記錄了正式發佈的歷史,而develop
分支做爲功能的集成分支。所以,master
分支的每次提交都應分配一個版本號。github
功能分支是從develop
中checkout
出來的新分支,每一個功能對應一個分支。shell
1.假設開發a功能:bash
git checkout -b feature-a develop
複製代碼
2.當新功能完成時,合併回develop分支。網絡
git checkout develop
git merge --no-ff feature-a
git push
git branch -d feature-a
複製代碼
1.當develop
分支開發到須要發佈時,從develop
分支拉出一個發佈分支,命名爲release-*
或release/*
。ide
git checkout -b release-0.1 develop
複製代碼
2.該分支用於發佈循環,只作bug修復、文檔生成等面向發佈的任務。新功能再也不添加到這個分支上。 3.一旦發佈完成,把發佈分支merge
到master
分支上。svn
git checkout master
git merge --no-ff release-0.1
git push
複製代碼
4.打tag
記錄版本號,方便跟蹤每次發佈。工具
git tag -a 0.1 -m "release 0.1 publish" master
git push --tags
複製代碼
5.把這些重新建發佈分支以來作的修改merge
到develop
分支。測試
git checkout develop
git merge --no-ff release-0.1
git push
複製代碼
6.最後刪除發佈分支
git branch -d release-0.1
複製代碼
當線上版本出現bug時,就須要用到維護分支,它用於快速給產品發佈版本打補丁。
1.從master
分支拉一個維護分支(這是惟一從master
分支拉出來的分支)。
git checkout -b hotfix master
複製代碼
2.修復完成後,立刻合併回master
和develop
。
git checkout master
git merge --no-ff hotfix
git push
git checkout develop
git merge --no-ff hotfix
git push
git branch -d hotfix
複製代碼
3.master
用新版本號打tag
。
git tag -a 0.2 -m "release 0.2 publish" master
git push --tags
複製代碼
master
和develop
分支分別記錄發佈和功能開發的歷史develop
master
和develop
GitHub 使用的工做流
master
上的東西都是可發佈的(已發佈或立刻發佈)master
拉一個名稱清晰的新分支push
到遠程倉庫merge
時,打開一個pull request
master
push
到master
後,應該當即發佈develop
做爲固定的持續集成和發佈分支
master
拉一個功能分支。develop
。develop
後,rebase master
到develop
,完成發佈。tag
。develop
分支的發佈版本合併回master
。master
),和當前開發的其餘分支不產生依賴關係master
始終是已發佈狀態暫時想不到。。。
Pull requests
不是一種工做流,而是一個能讓開發者更方便地進行協做的功能,能夠在提議的修改合併到正式項目以前對修改進行討論。這種方式對分支的合併有一些限制,例如只有項目維護者有權限合併分支到倉庫中。其工做方式:
push
分支修改到遠程倉庫中。Pull requests
。Pull Requests
。git commit --amend
最多見的用法是上次提交信息寫錯,或提交文件多了或漏了之時,從新提交覆蓋上一次提交。
其實它還有一個用法,就是用來合併提交。例如上次提交的修改並不徹底,再做修改以後能夠用該命令把本次提交與上次提交合並在一塊兒。
在須要回滾一次或屢次提交時,能夠用git reset
。因爲該命令比較危險,建議用於已經把最新提交推到遠程倉庫上的本地分支。
把已在暫時區的文件取消,恢復到已修改未暫存狀態。
git reset
後面可帶參數HEAD~[n]
(n >= 1)。表示回退到n
個提交以前。同時,它也能夠用來合併提交。下面的寫法與git commit --amend
結果是同樣的。
git reset HEAD~1
git commit
複製代碼
下面的用法則是合併了屢次提交
git reset HEAD~2
git commit
複製代碼
git reset
後面也能夠帶版本號,直接回退到指定版本。
git reset的三種參數
--hard
,如git reset --hard [version]
會執行如下操做:
--soft
,如 git reset --soft [version]
會執行上述的操做a。即只更改引用的指向,不改變暫存區和工做區。--mixed
或者不使用參數(默認爲--mixed
),如 git reset [version]
會執行上述的操做a和b。即更改引用的指向及重置暫存區,可是不改變工做區。--no-ff
是不快速合併的意思
git merge
的結果:
被merge的分支和當前分支在圖形上併爲一條線,被merge的提交點逐一合併到當前分支。
git merge --no-ff
的結果:
被merge的分支和當前分支不在一條線上,被merge的提交點還在原來的分支上,同時在當前分支上產生一個合併點。
git rebase
通常解釋爲變基
,也有解釋爲衍合
,我的以爲變基
比較容易理解。
git merge
是把兩個分支的代碼合併到一塊兒,其實git rebase
也是相同的做用,可是表現上是兩種不一樣的形式。
例如如今 dev 提交了一次,master 在此以後也提交了一次,兩個分支的狀態以下:
能夠看出git merge
後,不管加不加--no-ff
參數,提交點的順序都和提交的時間順序相同,即 master 的提交在 dev 以後,如圖:
而git rebase
後,順序就變成被rebase
的分支(master)全部提交都在前面,進行rebase
的分支(dev)提交都在被rebase
的分支以後,在同一分支上的提交點仍按時間順序排列,如圖:
從上面的圖能夠看出,dev 在rebase
master 後,分支發生了變化,本來是兩個分支,rebase
的結果看起來是: dev 是基於 master 的分支,且產生了一些新提交。
通常來講,rebase
後的 dev 和遠程的origin/dev
會發生分離,在命令行界面中會提示:
Your branch and 'origin/dev' have diverged,
and have 1 and 1 different commits each, respectively.
(use "git pull" to merge the remote branch into yours)
複製代碼
這時須要用git push -f
強制推送,覆蓋遠程分支。若使用了提示中的git pull
,結果會變成合並,併產生一個合併提交點。
注:慎用git push -f
!
注意git pull
時請加上--rebase
,理由下面會說。
在通常狀況下,加與不加--rebase
是沒有區別的。然而,結合上面說的git rebase
功能,能夠知道某個分支可能與其遠程分支發生分離,而當你pull
時,你的本地分支仍是和原來的遠程分支同樣,這時若是使用git pull
,則會變成你的本地分支和遠程分支合併,正確的作法是git pull --rebase
,纔會拉取到最新的分支。
因此推薦在任什麼時候候pull
遠程分支,最好加上--rebase
參數。
查看提交記錄的命令是git log
,而git reflog
的功能是查看本地操做記錄,如此一來能夠看到本地的commit
, merge
, rebase
等操做記錄。
6fe46ab HEAD@{0}: rebase finished: returning to refs/heads/dev
6fe46ab HEAD@{1}: rebase: dev modify a
2c92bcb HEAD@{2}: rebase: checkout master
9b26f5d HEAD@{3}: reset: moving to 9b26f5db1e8597b884c45114fbbff36c440da274
5531fc0 HEAD@{4}: merge master: Merge made by the 'recursive' strategy.
9b26f5d HEAD@{5}: checkout: moving from master to dev
複製代碼
Pro Git,Git工具書: http://iissnan.com/progit/html/zh/ch1_5.html
Git 工做流指南,介紹了幾種主流工做流: https://github.com/xirong/my-git/blob/master/git-workflow-tutorial.md
Gitflow 有害論: http://insights.thoughtworkers.org/gitflow-consider-harmful/
GitHub Flow: http://scottchacon.com/2011/08/31/github-flow.html
Google 的「主幹開發」(trunk-based development): http://www.ruanyifeng.com/blog/2016/07/google-monolithic-source-repository.html