往日干活,都是自己代碼一時爽,後人維護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 --amendgit 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。但在多人協作的倉庫中,你的修改會對其他人的遠程操作也構成影響,故三思而後行。

相關文章