Code Review 時能用上的一些 Git 操作
往日干活,都是自己代碼一時爽,後人維護XXX。如果可以的話,還是要堅持 Code Review (CR),不僅團隊內熟悉代碼風格,更能在學習他人優秀的代碼風格的同時補足自己的短板。
但是第一次 CR 時,如果你不是一個 git 高手,肯定會有那麼一些手足無措,比如提交代碼如何增量更新、混亂分支後如何撤銷變更等等,本文從只會 add/commit/push 三連的新手出發,看看 Code Review 時遇到的一些 Git 問題都要如何處理。
首先是配置了 git 密鑰,以及自己的用戶名和郵箱,過於基礎直接略過。
ssh-keygen // 生成 SSH Key // ... git config user.name "hijiangtao" // 配置用戶名 git config user.email "[email protected]" // 配置用戶郵箱
當我完成代碼的增刪改,一次再正常不過的提交,所需要用到的 git 命令也就這些:
git add -A git commit -m "MOD: Some changes" git push origin dev
如果在處理 Code Review 過程中你使用的是類似 gerrit 的工具,那麼你的 push 可能會需要稍作更改,比如在你的 .git/config
中自定義一個 push 到類似 HEAD:refs/for/dev
的命令,當然我們按照 GitHub 的標準流程往下走。
問題一:你本次提交的代碼需要更改
你的 commit 被打回了,那你需要修改後繼續 CR,如果你當前需要更改的 commit 就是本地最新 commit,那麼如下代碼即可
git add -A git commit --amend
輸入第二行命令後,你會進入一個文本編輯器界面,裏面有你的 commit 信息,修改後保存退出即可,然後
git push origin dev
其實,以上 git commit --amend
的意思是告訴 git 在不增加一個新的 commit-id 的情況下將修改內容追加到上一次 commit-id 中。
問題二:很早之前的 commit 需要更改
當你已經迭代到N.0版本時,發現1.0上的代碼需要修改怎麼辦?這時你的需求變成了修改最近一次提交以前的某次提交,這也是可以做的,不過當操作完成後,你的這次修改提交到最新提交之間的所有提交 hash 值都會改變。
這種操作在 git 中稱爲 變基
。你要小心操作變基,多用 git status
檢查你是否還處於變基流程中,防止誤操作會後續提交歷史造成影響。
首先查看提交日誌:
git log
找到你要修改的那次 commit,複製好它的前一次 commit hash 值以便確定修改範圍。然後我們使用 rebase 操作:
git rebase -i [Commit-range]
以上 [Commit-range]
可以是具體的 commit hash 值,也可以是類似 commit~n
或者 commit^^
這樣的形式,前者表示當前提交到 n 次以前的提交,後者 ^
符號越多表示的範圍越大。命令中的 -i
參數表示進入交互模式。在輸入命令後,你會進入一個文本編輯器,這時把你需要更改的 commit 中 開頭的 pick
改爲 edit
,然後保存退出。
其中,變基命令打開的文本編輯器中的commit順序跟 git log
看到的順序相反的;另外,變基命令也可以同時對多個 commit 進行修改,只需要修改將對應行前的 pick
都修改爲 edit
,後續操作完 commit 多次即可,但是祖先 commit 是不能修改的,即你一共存在10次 commit,那麼只能修改最近9次(重排、刪除以及合併都適用此規則)。
更改完代碼後利用如下命令提交代碼,進入文本編輯器的時候修改對應 commit 信息即可:
git add -A git commit --amend
確認修改完畢,即完成變基操作,這時候輸入下面一行:
git rebase --continue
然後查看下日誌,對比確認下變基前後的修改信息:
git log
這裏,剛剛提到的 pick 變爲 edit,還存在一些其他變數。
git rebase -i [Commit-range]
問題三:提交了錯誤的代碼
當你對以上命令還不熟的時候,你可能在操作中會混用 git commit --amend
和 git rebase --continue
;那麼當你發現把代碼提交到了錯誤 commit 下,該怎麼撤銷呢?這個相對好辦:
git revert [Commit-ID]
以上命令會補上一個提交將代碼恢復到你上一次提交之前的狀態,但注意這並不是抹去該 commit。
又或者你在 git rebase --continue
代碼時發現了衝突,這個時候請按照如下步驟操作:
- 首先,解決本地代碼的衝突;
-
然後,
git add -A
提交變更; -
最後,記得不是
git commit --amend
而是git rebase --continue
,防止錯誤提交代碼; - 如果你沒有按照第三步操作,那麼就乖乖 revert 好了;
問題四:挑選合入其他分支的提交
比如我在 dev 分支提交了一個 commit A,這個時候我想起來 dev_2 分支也需要這個提交,那麼我如何只“挑選” dev 分支的 A 到 dev_2 合入,而保持其他不變呢?此時, cherrt-pick
登場。 cherrt-pick
可以理解爲”挑揀”提交,它會獲取某一個分支的單筆提交,並作爲一個新的提交引入到你當前分支上。
git checkout dev git log --oneline -3 // A [Description]:dev commit 3 // B [Description]:dev commit 2 // C [Description]:dev commit 1 git checkout dev_2 git cherry-pick A git log --oneline -3 // A [Description]:dev commit 3 // ...
當然,如果 cherry-pick 遇到衝突,手動解決完 git commit
一次即可。
問題零:遠程 URL 變更
當然,還有一個小問題值得一提,你可能在克隆項目時用的是 HTTPS 方式,但卻覺得每次輸入用戶名密碼麻煩,最好的辦法是將遠程 URL 設置成 SSH 地址,這時就可以用到一個簡單的命令解決問題:
git remote set-url origin [email protected]:USERNAME/REPOSITORY.git
設置完成後,檢查一下 remotes 是否更新生效即可。
git remote -v // > origin [email protected]:USERNAME/REPOSITORY.git (fetch) // > origin [email protected]:USERNAME/REPOSITORY.git (push)
由於以上多個問題中涉及到的修改會直接對特定版本歷史進行修改,在需要推送到遠程倉庫時,存在不成功的情況,所以你可以強行 push。但在多人協作的倉庫中,你的修改會對其他人的遠程操作也構成影響,故三思而後行。