代碼評審中的代碼協同

作者 | 知憂

大神說:“Show me the code”,於是就有了代碼評審。

“Talk is cheap. Show me the code.”——Linus Torvalds, founder of Linux and Git.

代碼評審中同樣存在着“Talk is cheap. Show me the code”,語言無力時,直接上代碼吧。這就是我們今天要討論的話題——代碼評審中的代碼協同。

一 基於郵件列表的代碼評審

這是一種和代碼倉庫鬆耦合的代碼評審模式,100%的代碼都要經由一位或多位“仁慈的獨裁者”(benevolent dictator)代碼評審後才能合併入代碼倉庫。這種開發模式還需要開發者掌握一些命令行操作技巧以便完成代碼在倉庫和郵件列表之間的轉換。採用這個模式的項目不多,不過 Linux、Git 開源社區就是按照這種模式運作的。

1 代碼和郵件的相互轉換

代碼轉換爲電子郵件,要使用 git format-patch 命令。例如下面的命令將指定範圍的代碼提交(例如在 origin/master 之後的新提交)轉換爲電子郵件:

git format-patch origin/master..HEAD

生成的補丁文件的格式如下所示:

郵件頭中的 Subject: 字段是郵件標題,使用 [PATCH] 作爲標題前綴,以提交說明的第一行作爲標題內容。

更多的提交說明作爲郵件內容,和郵件頭之間用一個空行分隔開。

用分隔符 --- 作爲提交說明的結束。

在分隔符 --- 和 diff --git 開始的補丁內容之間的文字被忽略。通常此處內容是提交的變更統計,開發者也可以在此處寫入不宜列入提交說明中的附加說明。

git format-patch 命令有很多參數,要結合不同場景使用,例如:

一個特性由多個提交構成,分散在多個提交中的提交說明難以描述整個特性,可以使用 --cover-letter 參數,生成一封編號爲 0000 的郵件,作爲後續提交的摘要說明,便於評審者理解代碼。

一個特性通常會多次迭代,就需要爲每次迭代設置不同的版本。這就要用到 -v {num} 參數指定補丁的版本。版本將體現在郵件標題中,例如第二版本的補丁,郵件標題將使用 [PATCH v2] 作爲前綴。

回覆特定郵件,以便形成可追蹤的郵件線索,使用參數 --in-reply-to="{Message-ID}",爲電子郵件生成相關的 In-Reply-To: 和 References: 頭信息。

默認提交本身的作者、提交說明的簽名區(trailer)提及的貢獻者會自動添加爲郵件的收件人。要添加更多參與者,可以使用 --to={email}、--cc={email} 參數。

將電子郵件轉換爲代碼,則使用命令 git am [options...] mail... 。該命令會將郵件正確轉換爲 Git 倉庫中的提交。

使用 git send-email 命令,將包含代碼提交的郵件發送到郵件列表。

2 評審中的代碼片段轉換爲提交

代碼評審以郵件回覆的方式完成。注意郵件回覆都要求用純文本格式,否則會被郵件服務器退信。

代碼評審中發現小的文字錯誤,例如將 warning 寫成了 waring,評審者可能做出如下簡潔的回覆:

s/waring/warning/

這種約定俗成的格式大概是源於 sed 命令實現文本替換的語法。

評審者有時候會在回覆中貼上大段的代碼補丁,爲了使代碼補丁和郵件上下文做出區分,會使用特殊的剪刀分隔符將郵件中的評論和代碼補丁分隔開。

Subject: Re: whatever thread you're in

Somebody else said:> blah blah blah

I disagree. You should do it like this instead:

-- >8 --first line of commit message

more commit message---

diff --git ...

上面是 Peff(Jeff King)在郵件中給出的一個示範,看到其中的剪刀分隔符了麼?剪刀分隔符由多個減號(穿孔的分割線)和一個剪刀符號組成至少8個字符的分隔符。可選的分隔符有:-- 8< -- 、-- >8 -- 、-- %< -- 或 --- >% --- 等。

使用 git am --scissors 命令,能夠識別郵件中的剪刀分隔符,將郵件中的代碼轉換爲提交。

3 爲提交貢獻者署名

Git的提交元信息中只包含兩個署名信息,一個是提交的原始作者(Author),一個是將提交合入倉庫或者對提交做了修補的提交者(Committer),而在提交評審過程中有過貢獻的人往往不只兩人,如何致敬貢獻者呢?Git 社區的實踐是在提交尾部(trailer)添加貢獻者簽名。貢獻者簽名由一個被動語態的關鍵字和貢獻者ID組成,例如:

Signed-off-by: User < Email > :通常由代碼的貢獻者(Author)和代碼合入時的提交者(Committer)提供的簽名。可由命令 git commit -s 、 git am -s 等命令自動添加。

Reported-by: User < Email > :問題的報告者。

Helped-by: User < Email >:對提交有過幫助的人。

Reviewed-by: User < Email > :評審者。

可以通過 Git 項目倉庫的提交歷史,看到更多的簽名示例。

4 使用 GitHub PR 實現代碼到郵件的轉換

一個名爲 GitGitGadget 工具藉助 GitHub 強大的擴展能力,通過向 gitgitgadget/git 倉庫發送 pull request,實現提交到郵件的轉換,併發送到 Git 項目的郵件列表中。使用 GitGitGadget 參與 Git 社區代碼貢獻詳見。

二 GitHub 代碼評審中的協同

GitHub 使用 pull request 進行代碼評審,評論中的代碼塊兒也可以轉換爲提交。

1 代碼評論中嵌入代碼塊

下圖中,點擊評論工具欄第一個按鈕,可以在評論中嵌入代碼塊:

2 評論中代碼塊轉換爲提交

對 pull request 的源倉庫具有寫權限的用戶,可以將評審中的代碼庫轉換爲提交,如下圖所示:

於是代碼評審中會增加一個新的修正提交。

GitHub 的這個功能對於代碼評審中發現的一些小問題,還是非常方便的。但是大的修改就無能爲力了。

3 線下評審

對於功能複雜的 pull request,在線上瀏覽代碼不方便,也不能線上調試代碼,這時線下獲取並瀏覽代碼,就非常有必要了。

GitHub 的代碼倉庫中爲每一個代碼評審設置了特殊的關聯引用:

refs/pull/{ID}/head :關聯 pull request 的源提交。

refs/pull/{ID}/merge :對於沒有衝突的 pull request,這個引用指向一個成功的合併提交。

代碼評審者使用如下命令可以獲取 pull request (例如編號爲 123 的 PR)指向的提交:

git fetch origin refs/pull/123/headgit switch -d FETCH_HEAD

評審者可以線下調試 pull request 指向的代碼,但是對代碼做出的本地修改,沒有辦法直接更新到線上的代碼評審中。

阿里巴巴的雲效Codeup,支持線下到線上的代碼協同。

三 雲效Codeup代碼評審中的協同

無論是 GitHub 還是 Gitlab,開發者創建代碼評審首先需要將代碼推送到線上獨立的分支中(無論是在線上的派生倉庫,還是目標倉庫),然後再通過網頁選擇來源倉庫、分支及目標倉庫、分支,創建代碼評審。

GitHub 和 Gitlab 這種代碼評審方式,或者要引入冗餘的派生倉庫,或者需要爲開發者賦予在倉庫中的寫入權限,並容易引發雜亂的分支管理。

1 適合主幹開發的無分支創建代碼評審

雲效 Codeup 可以通過 git push 命令在客戶端直接創建代碼評審,無需創建派生倉庫或者在倉庫中創建特性分支。例如在客戶端執行如下命令:

git push origin HEAD:refs/for/master/topic1

該命令會在服務端創建新的代碼評審,或者如果已經存在相同用戶、相同命令創建的代碼評審則會更新評審中的提交。

建議安裝我們開源的 git-repo 工具,則可以用更簡單的命令行,實現從客戶端創建/更新代碼評審。

git pr

2 線下評審,線上協同

和 GitHub 類似,雲效 Codeup 創建的代碼評審都有一個特殊引用相關聯,格式爲:refs/merge-requests/{ID}/head。

代碼評審者可以使用 git fetch 命令獲取特定的代碼評審(以編號123爲例)指向的代碼,進行線下代碼評審。

git fetch origin refs/merge-requests/123/headgit switch -d FETCH_HEAD

如果安裝了 git-repo,可以使用下面更爲簡潔的命令:

git download 123

代碼評審者除了可以在本地倉庫中瀏覽、調試代碼,還可以更新代碼、創建提交,然後將本地新增提交更新到線上的代碼評審中。命令示例如下:

git pr -c 123

在雲效 Codeup,開發者和評審者可以基於代碼評審進行更爲流暢的代碼協同。

3 Git proc-receive 掛鉤

上述“線下評審、線上協同”功能的核心是 Git 的 proc-receive 掛鉤和 report-status-v2 新能力。這一功能由阿里巴巴貢獻給 Git 社區,並在 Git 2.29.0 發佈。

雲效 Codeup 彙集了阿里巴巴最新的代碼託管、代碼協同技術,希望能夠造福更多中國和世界的開發者。

識別二維碼領取創業加油禮包

走完線上 BUG 定位最後一公里

技術無“學歷” 從大專學校走出來的少年 AI 狂人

點個在看,讓更多人看見