這是一個系列文章,介紹學習 Git 的一個小遊戲 - githug,如果你是第一次看到,請先閱讀:
闖過這 54 關,點亮你的 Git 技能樹
闖過這 54 關,點亮你的 Git 技能樹(一)
闖過這 54 關,點亮你的 Git 技能樹(二)
闖過這 54 關,點亮你的 Git 技能樹(三)
闖過這 54 關,點亮你的 Git 技能樹(四)
沒想到第四彈在「開發者頭條」上獲得了
300 多個贊。
看來大家對這個小遊戲挺感興趣的,而且還有不少朋友在促更,今天就讓我們一鼓作氣打通最後的 14 關吧。
同樣,如對任何命令使用有疑問請看第一篇裏的推薦教程,也歡迎在下面留言,我會盡力提供幫助的。
第四十一關
項目時間長了,
git
倉庫會慢慢變大,如何優化?這個場景日常很少用到,而且不是必須用的,所以沒什麼概念。來看一下提示吧!
打開幫助之後輸入
/redundant
搜索關鍵字,一下就找到了一個 -d
的參數。第四十二關
有一次,我正在一個特性分支上開發一個功能,提交了幾次代碼,就在準備結束合併代碼的時候,然後產品經理說這個需求不用做了。
我強壓下心裏奔騰的一萬隻草泥馬,準備刪除這個分支,但在刪除之前想到有一個 commit 是對一個工具類的修改,還是有用的。
這是我就需要從特性分支上把這個 commit 摘出來,合到 master 分支上,再刪除特性分支。
這個題目就是類似的場景,先來看看特性分支叫什麼,然後找到需要「摘」出來的那個 commit:
查看了一下
log
命令的幫助,發現可以指定分支,這樣就省去了
checkout 到 new-feature 分支的步驟。上圖中最後的一次提交就是我們需要「摘」出來的,複製它的 Hash。
順利過關!
第四十三關
我們在開發的過程中,爲了不影響當前正在做的事情,會把一些不那麼緊急的任務使用 TODO
註釋在代碼裏,現代的
IDE 都能幫我們識別這些註釋並在一個單獨的窗口中羅列出來。
當然,不借助 IDE,光憑系統命令或 git 命令也是可以做到的。
第四十四關
查看 log,git
log --oneline
,可以看到中間的 commit message 有一個拼寫錯誤。
看一下提示,可以在 rebase 的時候指定
-i
參數:查看一下幫助就知道是
interactive
的意思:在打開的 Vim 窗口中將第一行的
pick
改爲 r
,表示:使用
commit,並且修改 commit message。修正拼寫錯誤的
coommit
。第四十五關
當我使用 TDD 方式進行開發,會進行非常頻繁小步的提交,這樣在其他同事看來就缺乏完整性,也會增加後續維護成本。
所以 git 讓我可以在 push 到遠程倉庫之前,對 commit 歷史進行修改合併,把多個 commit 合併成一個。
用 git
log --oneline
看一下提交記錄:
從提交記錄可以看出,它提示我們將最後三個 commit 都合併到第二個 commit - Adding README 中。
接着執行
git
rebase -i HEAD~4
:第一個 commit 爲
pick
,後三個改爲 s
,意思是使用這個
commit,但將它合併到前一個 commit 中去。保存退出,會提示我們編輯 commit message,再次保存退出後,查看一下提交記錄:
第四十六關
題目要求在 merge 特性分支時,把所有的新提交合併成一個,先來看看 master 分支當成的狀態:git
log --oneline
:
再看一下
git
log long-feature-branch --oneline
:最後 master 分支狀況如圖,只用一個 commit,包含了 long-feature-branch
所有的修改:
第四十七關
提交順序錯亂時,也可以使用 git
rebase -i
進行調整。
先看看 Log,最後兩個提交顛倒了位置:
執行
git
rebase -i HEAD~2
,將兩行 pick xxx 代碼交換位置即可。第四十八關
代碼中不知道什麼時候引入了 bug,不過沒關係,我們有自動化測試。
我們可以不斷手工 checkout 到某個 commit,結合二分法查找快速定位到引入 bug 的那一個 commit。
不過這種純手工重複的事情,已經包含在 git 的命令中了,就是 bisect
讀一下
git
help bisect
,可以找到這個例子:我們知道 HEAD 的代碼是有問題的,而第一個 commit 的代碼是沒問題的。
通過
git
log
獲得第一個 commit 的 Hash,就可以執行 bisect 命令:紅線部分已經清楚地告訴我們是哪個 commit 引入的 bug 了。
第四十九關
有時開發了一個特性沒提交,接着又開發了另一個特性。
作爲一個自律的程序員,應該是要分兩次提交的,如果修改的是不同的文件,那可以輕鬆地通過 add 不同的文件進行兩次提交。
但這次好巧不巧的是居然修改了同一個文件,怎麼辦?看看提示:
原來 git add 的最小粒度不是「文件」,而是 hunk(代碼塊)。
git
help add
然後查找 hunk
:執行如下命令:
Git 會讓我們有機會選擇對每一個 hunk 做什麼樣的操作。這裏修改同一個位置,在一個 hunk 裏,根據提示我們還要輸入
e
手工編輯
hunk。將第 5 行刪除,保存退出,再看當前狀態:
git
diff --cached
:第五十關
正在特性分支上開發一個功能,被頭兒叫去修了一個緊急的 bug,修完後發現:媽蛋,那個特性分支叫啥?忘記了!
當然,作爲一個自律的程序員,一般是不是出現這樣的場景的。
這種情況說明分支命名太沒有規律,或者分支太多,不然可以通過 git
branch
看一下,也能很快找到特性分支。
先看一下提示吧:
哦,原來有個命令叫
git
reflog
,來看看幫助文檔 - git
help reflog
,看起來這個命令非常強大,不過我們這裏只用到簡單用法就可以了:上圖中第二行就顯示了我們之前工作的特性分支。
第五十一關
有時代碼 push 到遠程倉庫後發現某一塊代碼有問題,我們可以通過 revert
命令將特定
commit 完全恢復。
首先我們要找到需要 revert 的 commit 的 hash:
完全過程如下:
第五十二關
剛剛把最新的一次提交給毫無保留的扔掉,馬上就改了主意,怎麼辦?世界上有後悔藥嗎?
有的,只要進行 git 版本控制的一切都能找得回來。看下提示先:
提示說被我們拋棄的那個 commit 像孤魂野鬼一樣在外遊蕩,還沒有被鬼差送入地獄,我們還能通過
git
reflog
找到它的代號。找到它的 Hash 後就通過 cherry-pick 將它找回來:
第五十三關
衝突合併是使用版本控制非常常見的了,居然在這麼靠後的位置纔出來。
編輯衝突的文件 poem.txt,刪除 Git 添加的標識衝突的行。
別忘了,還要
git
add poem.txt
然後 git
commit
。第五十四關
submodule 是 Git 組織大型項目的一種方式,通常可把第三方依賴作爲 submodule 包含進來,這個 submodule 本身也是一個獨立的 Git 項目。
第五十五關
最後這一關並非測試使用 GitHub 的能力,而是期望大家貢獻代碼,包括增加更多關卡,修復 Bug 或者完善文檔。
我當初是準備翻譯中文版,結果工作量不小,拖的太久最後不了了之了。
希望你能對開源社區貢獻自己的一分力量!哪怕 Star
一下也是對作者莫大的鼓舞!