git 入門教程之緊急修復

雪之夢技術驛站發表於2019-03-22

和往常一樣,每個人團隊開發者都在自己的本地分支上進行日常工作,相互獨立又相互聯絡,一直以來相安無事,可是某天下午,上級領導突然急衝衝的打電話告訴你線上出bug了,需要你緊急修復,下班之前必須解決!

我們天生就是創造 bug 的特殊群體,每天都在和各種各樣的 bug 打交道,早已經習慣了這樣的工作節奏,再也沒有當初剛剛遇到緊急問題的手足無措,先喝杯茶,冷靜一下,然後彙報領導說:放心吧!保證30min 內解決問題!

背景

學習了分支操作的相關知識,團隊內部就基本的開發流程達成一致:

假設線上是主幹 master 分支,開發是 dev 分支,團隊成員是自定義 custom 分支,平時開發時在大家在各自 custom 分支上工作,完成分配任務後再合併到開發 dev 分支,等到開發分支功能穩定後,由專案領導負責合併到主幹分支 master .

上述流程只是開發流程的簡化版,實際情況更加複雜,後續再介紹 gitflow 工作流相關知識.

由於是線上出現 bug,理所當然是基於 master 分支檢出臨時分支,修復分支代號為 issue-110,然後定位 bug 並提交,最後再合併到 master 分支,如此一來成功修復 bug,完成既定任務,心安理得準備下班回家!

如果真的向上述步驟那樣操作,顯然還不夠冷靜,剛才那一杯茶算是白喝了!因為這樣操作可能會丟失現場資料,那很多工作豈不是白做了,下面簡單演示一下:

錯誤示例

(一). 事發前正在自定義的 snow 分支上愉快編碼中...

# 線上分支 `master`,開發分支 `dev`,自定義分支 `snow`,當前正處於自定義分支
$ git branch
  dev
  master
* snow
# 接到領導電話前正在自定義 `snow` 分支上進行愉快編碼中...
$ echo "Happy coding" >> test.txt
$ git add test.txt
$ git commit -m  "Happy coding"
複製程式碼

git-branch-snow.png

(二). 事發時直接檢出主分 master 分支,並緊急修復 bug .

(2.1) 基於 master 分支檢出 issue-110 分支,並修復提交.

# 注意: 事發時正在思考人生,此時更改尚未新增到暫存區!
$ echo "who am i" >> test.txt

# 當前情況下,預設不允許直接切換到其他分支,因為工作區更改會被重寫,這裡為了演示錯誤示例,強制切換!
$ git checkout -f master 

# 基於主幹 `master` 分支檢出修復 `issue-110`分支
$ git checkout -b issue-110
Switched to a new branch 'issue-110'

# 定位線上 `bug`並修復,假設將 `fast forward` 更改為 `fast forward not recommend`,瞬間修復 `bug`有沒有!
$ cat test.txt
add test.txt
see https://snowdreams1006.github.io/git/usage/remote-repository.html
learn git branch
see https://snowdreams1006.github.io/git/usage/branch-overview.html
git commit c1
git commit c2 and c3
git checkout -b dev
fast forward
$ vim test.txt
$ cat test.txt
add test.txt
see https://snowdreams1006.github.io/git/usage/remote-repository.html
learn git branch
see https://snowdreams1006.github.io/git/usage/branch-overview.html
git commit c1
git commit c2 and c3
git checkout -b dev
fast forward not recommend

# 修復 `bug` 後,提交更改並備註已修復
$ git add test.txt
$ git commit -m "fix bug about issue-110"
[issue-110 e60c8ad] fix bug about issue-110
 1 file changed, 1 insertion(+), 1 deletion(-)
sunpodeMacBook-Pro:git-demo sunpo$ git status
On branch issue-110
nothing to commit, working tree clean
$ 
複製程式碼

git-branch-issue-110.png

(2.1) 切換到主幹 master 分支,併合並修復 issue-110 分支

# 切換回 `master` 分支,合併修復 `issue-110` 分支
$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.
$ git merge issue-110
Updating 3fe94c0..e60c8ad
Fast-forward
 test.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

# 驗證 `bug` 已修復: 更改為 `fast forward not recommend`
$ cat test.txt
add test.txt
see https://snowdreams1006.github.io/git/usage/remote-repository.html
learn git branch
see https://snowdreams1006.github.io/git/usage/branch-overview.html
git commit c1
git commit c2 and c3
git checkout -b dev
fast forward not recommend
$ 
複製程式碼

git-branch-fixbug-master.png

(三). 事發後切換回自定義 snow 分支,打算下班回家.

# 切換回 `snow` 分支,發現丟失了事發前的未儲存更改:`who am i`
$ git checkout snow
Switched to branch 'snow'
$ cat test.txt
add test.txt
see https://snowdreams1006.github.io/git/usage/remote-repository.html
learn git branch
see https://snowdreams1006.github.io/git/usage/branch-overview.html
git commit c1
git commit c2 and c3
git checkout -b dev
fast forward
Happy coding
$ 
複製程式碼

git-branch-fixbug-snow.png

現在還打算下班嗎?你所做的更改因為沒有提交或者不能提交造成全部丟失!

結果

因為手頭工作進行到一半無法提交或者忘記提交等原因,為了臨時修復緊急 bug直接切換到目標分支再回來時發現更改全部丟失,相當於那部分工作白忙活了!

正確示例

經過上述錯誤示例的慘痛教訓後,再也不敢輕易切換分支了,原因在於工作區更改並沒有被提交,或者說不能提交,如果能夠有一種機制來保護案發現場,這樣我們就能放心切換到其他分支工作,回來時一切如初,那該多好?

幸運的是,git 確實提供這麼一種機制,git stash 命令臨時儲存工作區,類似"草稿箱"作用.

(一). 恢復工作區丟失更改,並使用 git stash 命令儲存現場.

# 修復工作區丟失更改: 同樣未新增到暫存區
$ echo "learn git stash" >> test.txt
$ cat test.txt
add test.txt
see https://snowdreams1006.github.io/git/usage/remote-repository.html
learn git branch
see https://snowdreams1006.github.io/git/usage/branch-overview.html
git commit c1
git commit c2 and c3
git checkout -b dev
fast forward
Happy coding
learn git stash

# 保護現場: 儲存到"草稿箱"
$ git stash
Saved working directory and index state WIP on snow: 93227ba Happy coding
複製程式碼

(二). 切換到開發 dev 分支併合並修復 issue-110 分支.

# 切換到開發 `dev` 分支
$ git checkout dev
Switched to branch 'dev'
sunpodeMacBook-Pro:git-demo sunpo$ git status
On branch dev
nothing to commit, working tree clean
# 合併修復 `issue-110` 分支
$ git merge issue-110
Updating 3fe94c0..e60c8ad
Fast-forward
 test.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
sunpodeMacBook-Pro:git-demo sunpo$ git status
On branch dev
nothing to commit, working tree clean
$ 
複製程式碼

(三). 切換回自定義 snow 分支,並恢復工作現場.

# 切換回自定義 `snow` 分支
$ git checkout snow
Switched to branch 'snow'
sunpodeMacBook-Pro:git-demo sunpo$ git status
On branch snow
nothing to commit, working tree clean
$ 
複製程式碼

git status 命令返回結果怎麼顯示工作區是乾淨的,好不容易才將丟失的更改找回來怎麼又不見了?!逗我玩?

冷靜,冷靜,不要慌,既然工作現場已經儲存到"草稿箱",那我們想要找回總要去"草稿箱"才能取出來吧?現在讓我們看一下"草稿箱"有沒有我們的工作現場?

# 檢視儲存的"草稿箱"列表
$ git stash list
stash@{0}: WIP on snow: 93227ba Happy coding
$ 
複製程式碼

這裡的 stash@{0} 是草稿 id,因為"草稿箱"允許儲存多條草稿!

現在放心了吧,儲存的"草稿"安然無恙躺在未知的某個地方,現在我們想辦法恢復回工作區即可!

  • git stash apply 恢復草稿,然後 git stash drop 刪除草稿
  • git stash pop 恢復並刪除草稿
# 恢復工作現場
$ git stash pop
On branch snow
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   test.txt

no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (b0c8ddc034d21f31204c82e9838fc5d4c01a49a8)

# 工作現場已恢復,更改未新增到暫存區,`learn git stash` 又恢復了!
$ git status
On branch snow
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   test.txt

no changes added to commit (use "git add" and/or "git commit -a")
$ cat test.txt
add test.txt
see https://snowdreams1006.github.io/git/usage/remote-repository.html
learn git branch
see https://snowdreams1006.github.io/git/usage/branch-overview.html
git commit c1
git commit c2 and c3
git checkout -b dev
fast forward
Happy coding
learn git stash
複製程式碼

結果

不論手頭工作有沒有提交,一旦工作區儲存到"草稿箱"後,就放心大膽切換分支進行工作,回來時歲月靜好,一切如初!

小結

緊急修復 bug 時,可以通過 git stash 保護工作現場,然後再切換到目標分支,檢出修復分支,完成修復後切換到目標分支,合併修復分支,最後刪除修復分支,此時再切換回本地分支後一切如初!

  • 工作區更改新增到"草稿箱" : git stash,支援多次新增到"草稿箱"
  • 列出"草稿箱"內容 : git stash list
  • 恢復"草稿箱"內容 : git stash apply
  • 刪除"草稿箱"內容 : git stash drop
  • 恢復並刪除"草稿箱"內容 : git stash pop
  • 恢復|刪除指定"草稿箱"內容 : git stash <stash-id>,例如 git stash apply stash@{0}

相關文章