如何優雅地使用 Git

版本樹 / graph / network

  • 乾淨簡潔清晰
  • 提交信息明確
  • 易維護易讀

舉個反例:前端

image

舉個正例:git

image

Git 文件狀態

經過 git status 查看shell

  • untracked 新文件未加入版本管理
  • unmodify
  • modified
  • staged 用 git add 暫存

git diff --stagedgit diff --cached 可查看已暫存文件和上次提交的區別緩存

分支和 tag

合理使用分支,分支的好處:bash

  • 同時開發不一樣功能不衝突,可獨立測試
  • 可集中解決衝突
  • 區分功能或將來某一版本

tag 的做用是對某個提交點打上標籤,發佈版本後打 tag,便於之後回滾特定版本,而不須要 revert。markdown

tag 是對某一版本的記錄。測試

開發新功能步驟

  1. 從開發分支拉一個功能分支
  2. 功能分支開發和測試
  3. 功能分支 rebase 開發分支(爲何)
  4. 功能分支合併到開發分支

注意:

  • 一次提交作一件事,寫清楚 comment
  • 每次 pull 遠程分支時使用 git pull --rebase
  • 分支從哪拉出來,最後合到哪回去
  • 合併以前先 rebase

fix bug 步驟

測試線bug的修復

和開發步驟相似this

線上bug的修復

  1. 從master拉一個fix分支(爲何是master)
  2. 測試完後 rebase master
  3. 合併回master

Git 使用技巧

rebase 和 merge

git rebase通常解釋爲變基,也有解釋爲衍合spa

git mergegit rebase 均可以整合兩個分支的內容,最終結果沒有任何區別,可是變基使得提交歷史更加整潔。命令行

例如如今 dev 提交了一次,master 在此以後也提交了一次,兩個分支的狀態以下:

image

git merge 的結果:

image

git rebase 的結果:

image

提交點順序

  • git merge後,提交點的順序都和提交的時間順序相同,即 master 的提交在 dev 以後。
  • git rebase後,順序變成被rebase的分支(master)全部提交都在前面,進行rebase的分支(dev)提交都在被rebase的分支以後,在同一分支上的提交點仍按時間順序排列。

分支變化

  • dev 在 rebase master 後,由原來的兩個分岔的分支,變成重疊的分支,看起來 dev 是從最新的 master 上拉出的分支。

何時使用 rebase / merge

假設場景:從 dev 拉出分支 feature-a。那麼當 dev 要合併 feature-a 的內容時,使用 git merge feature-a;反過來當 feature-a 要更新 dev 的內容時,使用 git rebase dev

使用時主要看兩個分支的"主副"關係。

注意

通常來講,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 merge --no-ff

--no-ff 是不快速合併的意思

與 git merge 的區別

git merge的結果:

被merge的分支和當前分支在圖形上併爲一條線,被merge的提交點逐一合併到當前分支。

image

git merge --no-ff的結果:

被merge的分支和當前分支不在一條線上,被merge的提交點還在原來的分支上,同時在當前分支上產生一個新的提交點。

image

————————————————————

git rebase -i 操做

用於整理提交和提交信息,貌似不太好用,看演示:

git rebase -i dev 後進入以下界面。

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,達到合併提交的目的,其中r是保留提交,修改提交信息,f是保留提交可是丟棄此次提交信息。

1 r ffc75a4 修改
2 f 6c2217f bbb
3 r a615960 修改a 1
4 f e4817b3 修改a 2
5 f 8550690 修改a 3
複製代碼

而後進入編輯兩個打了r的提交信息的界面,修改提交信息保存便可。

這時候再看log,剛纔的5次提交已經變成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 的區別

在通常狀況下,加與不加 --rebase 是沒有區別的。

然而,從上面說的 git rebase 功能得知,某個分支可能與其遠程分支發生分離,而當你 pull 時使用 git pull,則會變成你的本地分支和遠程分支合併。

正確的作法是git pull --rebase,纔會拉取到最新的分支。

所以推薦在任什麼時候候 pull 遠程分支,最好加上 --rebase 參數。

————————————————————

reset 和 revert

  • git reset 修改 HEAD 指向的位置
  • git revert還原某一個提交,併產生新提交來記錄本次還原

git reset 經常使用命令

  • git reset HEAD {filename}: 取消暫存文件,恢復到已修改未暫存狀態。

  • git reset HEAD~{n}: 表示回退到n個提交以前。它也能夠用來合併提交,下面的寫法與 git commit --amend 結果是同樣的。

git reset HEAD~1
git commit
複製代碼
  • git reset {version}: 後面帶版本號,直接回退到指定版本。

  • git reset的三種參數:

    1. 使用參數--hard,暫存區、工做區和 HEAD 指向的目錄樹內容相同。
    2. 使用參數--soft,只更改 HEAD 的指向,暫存區和工做區不變。
    3. 使用參數--mixed或者不帶參數(默認爲--mixed),更改引用的指向及重置暫存區,可是不改變工做區。

————————————————————

git reflog

查看提交記錄的命令是git log,而git reflog的功能是查看本地操做記錄,能夠看到本地的commit, merge, rebase等操做記錄,並帶有版本號。

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內容
a7f47b2 HEAD@{11}: checkout: moving from dev to feature-rebase-i
複製代碼

————————————————————

git stash

把工做區內容緩存到一個棧裏,以後用 git stash pop取出。在未提交工做區內容,可是想切到其餘分支時很是有用。

注意

不建議同一時間段在不一樣分支都使用 git stash,涉及到多個分支的情形仍是先 commit 較好,不push到遠程,下次 commit 時可用 --amend 合到上次提交中。

做者:丁香園前端團隊——lwenn

相關文章
相關標籤/搜索