版本樹 / graph / network
- 干凈簡(jiǎn)潔清晰
- 提交信息明確
- 易維護(hù)易讀
舉個(gè)反例:

舉個(gè)正例:

Git 文件狀態(tài)
通過 git status 查看
- untracked 新文件未加入版本管理
- unmodify
- modified
- staged 用 git add 暫存
git diff --staged 或 git diff --cached 可查看已暫存文件和上次提交的區(qū)別
分支和 tag
合理使用分支,分支的好處:
- 同時(shí)開發(fā)不同功能不沖突,可獨(dú)立測(cè)試
- 可集中解決沖突
- 區(qū)分功能或未來某一版本
tag 的作用是對(duì)某個(gè)提交點(diǎn)打上標(biāo)簽,發(fā)布版本后打 tag,便于以后回滾特定版本,而不需要 revert。
tag 是對(duì)某一版本的記錄。
開發(fā)新功能步驟
- 從開發(fā)分支拉一個(gè)功能分支
- 功能分支開發(fā)和測(cè)試
- 功能分支 rebase 開發(fā)分支(為什么)
- 功能分支合并到開發(fā)分支
注意:
- 一次提交做一件事,寫清楚 comment
- 每次 pull 遠(yuǎn)程分支時(shí)使用
git pull --rebase - 分支從哪拉出來,最后合到哪回去
- 合并之前先 rebase
fix bug 步驟
測(cè)試線bug的修復(fù)
和開發(fā)步驟類似
線上bug的修復(fù)
- 從master拉一個(gè)fix分支(為什么是master)
- 測(cè)試完后 rebase master
- 合并回master
Git 使用技巧
rebase 和 merge
git rebase一般解釋為變基,也有解釋為衍合。
git merge 和 git rebase 都可以整合兩個(gè)分支的內(nèi)容,最終結(jié)果沒有任何區(qū)別,但是變基使得提交歷史更加整潔。
例如現(xiàn)在 dev 提交了一次,master 在此之后也提交了一次,兩個(gè)分支的狀態(tài)如下:

git merge 的結(jié)果:

git rebase 的結(jié)果:

提交點(diǎn)順序
-
git merge后,提交點(diǎn)的順序都和提交的時(shí)間順序相同,即 master 的提交在 dev 之后。 -
git rebase后,順序變成被rebase的分支(master)所有提交都在前面,進(jìn)行rebase的分支(dev)提交都在被rebase的分支之后,在同一分支上的提交點(diǎn)仍按時(shí)間順序排列。
分支變化
- dev 在 rebase master 后,由原來的兩個(gè)分岔的分支,變成重疊的分支,看起來 dev 是從最新的 master 上拉出的分支。
什么時(shí)候使用 rebase / merge
假設(shè)場(chǎng)景:從 dev 拉出分支 feature-a。那么當(dāng) dev 要合并 feature-a 的內(nèi)容時(shí),使用 git merge feature-a;反過來當(dāng) feature-a 要更新 dev 的內(nèi)容時(shí),使用 git rebase dev。
使用時(shí)主要看兩個(gè)分支的"主副"關(guān)系。
注意
一般來說,rebase后的 dev 和遠(yuǎn)程的origin/dev會(huì)發(fā)生分離,在命令行界面中會(huì)提示:
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)
這時(shí)需要用git push -f強(qiáng)制推送,覆蓋遠(yuǎn)程分支。若使用了提示中的git pull,結(jié)果會(huì)變成合并,并產(chǎn)生一個(gè)合并提交點(diǎn)。
慎用git push -f!
————————————————————
git merge --no-ff
--no-ff 是不快速合并的意思
與 git merge 的區(qū)別
git merge的結(jié)果:
被merge的分支和當(dāng)前分支在圖形上并為一條線,被merge的提交點(diǎn)逐一合并到當(dāng)前分支。

git merge --no-ff的結(jié)果:
被merge的分支和當(dāng)前分支不在一條線上,被merge的提交點(diǎn)還在原來的分支上,同時(shí)在當(dāng)前分支上產(chǎn)生一個(gè)新的提交點(diǎn)。

————————————————————
git rebase -i 操作
用于整理提交和提交信息,貌似不太好用,看演示:
git rebase -i dev 后進(jìn)入如下界面。
1 pick ffc75a4 修改
2 pick 6c2217f bbb
3 pick a615960 修改a 1
4 pick e4817b3 修改a 2
5 pick 8550690 修改a 3
6
7 # Rebase 3190ea4..8550690 onto 3190ea4 (5 command(s))
8 #
9 # Commands:
10 # p, pick = use commit
11 # r, reword = use commit, but edit the commit message
12 # e, edit = use commit, but stop for amending
13 # s, squash = use commit, but meld into previous commit
14 # f, fixup = like "squash", but discard this commit's log message
15 # x, exec = run command (the rest of the line) using shell
16 # d, drop = remove commit
17 #
18 # These lines can be re-ordered; they are executed from top to bottom.
19 #
20 # If you remove a line here THAT COMMIT WILL BE LOST.
21 #
22 # However, if you remove everything, the rebase will be aborted.
23 #
24 # Note that empty commits are commented out
修改commit注釋前面的pick,達(dá)到合并提交的目的,其中r是保留提交,修改提交信息,f是保留提交但是丟棄這次提交信息。
1 r ffc75a4 修改
2 f 6c2217f bbb
3 r a615960 修改a 1
4 f e4817b3 修改a 2
5 f 8550690 修改a 3
然后進(jìn)入編輯兩個(gè)打了r的提交信息的界面,修改提交信息保存即可。
這時(shí)候再看log,剛才的5次提交已經(jīng)變成2次提交。
commit 94784f0c163bc4b2970f73066c91fac16b64be32
Author: ***
Date: Mon Jan 8 17:01:57 2018 +0800
修改a
commit 52907b261821afb0c38754ba95545ff8826910db
Author: ***
Date: Mon Jan 8 16:28:05 2018 +0800
修改b
————————————————————
git pull --rebase
與 git pull 的區(qū)別
在一般情況下,加與不加 --rebase 是沒有區(qū)別的。
然而,從上面說的 git rebase 功能得知,某個(gè)分支可能與其遠(yuǎn)程分支發(fā)生分離,而當(dāng)你 pull 時(shí)使用 git pull,則會(huì)變成你的本地分支和遠(yuǎn)程分支合并。
正確的做法是git pull --rebase,才會(huì)拉取到最新的分支。
因此推薦在任何時(shí)候 pull 遠(yuǎn)程分支,最好加上 --rebase 參數(shù)。
————————————————————
reset 和 revert
-
git reset修改 HEAD 指向的位置 -
git revert還原某一個(gè)提交,并產(chǎn)生新提交來記錄本次還原
git reset 常用命令
git reset HEAD {filename}: 取消暫存文件,恢復(fù)到已修改未暫存狀態(tài)。git reset HEAD~{n}: 表示回退到n個(gè)提交之前。它也可以用來合并提交,下面的寫法與git commit --amend結(jié)果是一樣的。
git reset HEAD~1
git commit
git reset {version}: 后面帶版本號(hào),直接回退到指定版本。-
git reset的三種參數(shù):- 使用參數(shù)
--hard,暫存區(qū)、工作區(qū)和 HEAD 指向的目錄樹內(nèi)容相同。 - 使用參數(shù)
--soft,只更改 HEAD 的指向,暫存區(qū)和工作區(qū)不變。 - 使用參數(shù)
--mixed或者不帶參數(shù)(默認(rèn)為--mixed),更改引用的指向及重置暫存區(qū),但是不改變工作區(qū)。
- 使用參數(shù)
————————————————————
git reflog
查看提交記錄的命令是git log,而git reflog的功能是查看本地操作記錄,可以看到本地的commit, merge, rebase等操作記錄,并帶有版本號(hào)。
b3bf634 HEAD@{0}: rebase -i (finish): returning to refs/heads/feature-rebase-i
b3bf634 HEAD@{1}: rebase -i (fixup): 完善a中的判斷和輸出
dd19de3 HEAD@{2}: rebase -i (fixup): # This is a combination of 2 commits.
c138acf HEAD@{3}: rebase -i (reword): 完善a中的判斷和輸出
a7f47b2 HEAD@{5}: rebase -i (start): checkout dev
a472934 HEAD@{6}: rebase: aborting
a7f47b2 HEAD@{7}: rebase -i (start): checkout dev
a472934 HEAD@{8}: commit: 添加a輸出
c84d5b7 HEAD@{9}: commit: 添加a中的判斷
a5a6e64 HEAD@{10}: commit: 修改a內(nèi)容
a7f47b2 HEAD@{11}: checkout: moving from dev to feature-rebase-i
————————————————————
git stash
把工作區(qū)內(nèi)容緩存到一個(gè)棧里,之后用 git stash pop取出。在未提交工作區(qū)內(nèi)容,但是想切到其他分支時(shí)非常有用。
注意
不建議同一時(shí)間段在不同分支都使用 git stash,涉及到多個(gè)分支的情形還是先 commit 較好,不push到遠(yuǎn)程,下次 commit 時(shí)可用 --amend 合到上次提交中。