聊聊代碼提交那些事

2021-02-08 華為開發者社區





為何要聊「代碼提交」這麼小的一件事情?隨著團隊人數越來越多,提交代碼這件事,變得複雜起來。甚至極端一點說,任何複雜度的軟體項目,也無非是要管好兩件事情:需求和代碼。


順著這條線索,我們可以觀察到一種螺旋上升的現象:



需求再次爆炸……


從個體戶到小團隊、從小團隊到大兵團,需求的數量、人員的數量、代碼的數量,都會有百倍、千倍甚至更加驚人的增長。在這種變化的過程中,不僅僅是人數需要增加,相應的工具、以及管理流程,也要發生變化。


本文主要探討:如何管好代碼這件事情,這篇文章不會介紹基礎知識,而僅僅是一種邏輯上的梳理。關於:代碼提交、代碼管理、團隊管理、研發質量管理等等內容。



在單槍匹馬乾活的日子裡,很多事情都相當簡單。甚至,在當年我們都不知道什麼叫版本管理。我們在自己的機器上寫代碼,當然也在自己的機器上完成編譯,然後自己試用一下,算是「測試」。


如果是伺服器端的開發,我們就直接登錄到伺服器上,打開 vim,直接寫代碼,寫完了保存就 OK。


當年我還在寫 PHP 程序的時候,最喜歡的編輯器是 EditPlus,因為它支持 FTP 連結到伺服器,直接就能修改伺服器上的文件,Ctrl+S 以後,再刷一下瀏覽器,結果就出來了。


這樣的開發習慣,當我成為 Java 程式設計師的時候,也影響到了我的技術選型。我最喜歡的 java web server 是 resin。最大的一個原因是:使用 resin 的服務,修改 java 代碼,也不必編譯、然後再重啟服務。



當我們的項目,越來越複雜、代碼越來越多時,就開始需要版本管理的工具了。


在事情還不那麼複雜的時候,我們可以將修改代碼的原因,記錄在注釋裡。但是,如果一個文件被反覆修改,那麼將修改理由記錄在提交說明裡,將是一個更好的選擇。


一個原本正確的代碼,被改壞了,需要回退。這個時候我們不能僅僅依靠自己的記憶力,恢復代碼到原來的樣子。


當協同開發的人超過一個,就可能會出現:一個文件,曾經被多個人修改過的情況。這時:找到當時那個幹了壞事的傢伙,就變得非常重要。


所以,我們至少應該能夠有地方記錄:誰,在什麼時候,因為什麼理由,修改了一個文件(或者修改了一組文件)。



我曾經用過的最早的版本管理工具,叫做 Visual SourceSafe,簡稱 VSS。也許是資歷太淺,VSS 就是我用過的,最難用的版本管理工具了。


為了保證原始碼的安全,VSS 採用了最為極端的獨佔工作模式。當我想要修改某個文件的時候,就把這個文件 check out 出來,然後在我修改完成,並再次 check in 之前,任何其他人都無法 check out 這個文件,當然也無法修改這個文件。


因此,當時最常見的辦公室對話是:是誰,又籤出了文件?那個誰誰誰,你快點改啊,我也要改這個文件!


事隔多年以後,我在維基百科上看到:「VSS 雖然是微軟公司的產品,但微軟內部卻很少使用它。」 真是欲哭無淚。


本質上,VSS 是一個將代碼安全的需求,置於團隊研發效率之上的工具。幸好,這個產品已經沒人用了。



在人數很少的時候,VSS 實際上也能工作得很好。但是,當軟體越來越複雜,需求越來越多的時候,我們只能招聘更多的工程師,並且催促他們儘快上手開始寫代碼。


為了幫助一群人,能夠順暢地協作,我們需要創造諸多的概念、流程、工具與協作方法。


1、版本號:實質上對為一個階段的工作成果命名,按照某種慣例,特別不成熟的成果,我們會命名為 0.1,甚至 0.01;第一個可以正式發布的版本,我們會命名為 1.0。預發布的版本,我們會稱之為 1.01-alpha;然後是 1.01-beta;最終我們會發布一個 1.01-final;


這些做法實際上意味著:版本號具有隱含的質量屬性。這樣的質量屬性,即方便對外公告,也方便內部管理;更進一步,從搜集 bug 的角度來說,我們也可以較為準確地將某一個 bug,記錄在特定的版本之下,直到他們在每一個版本之後,被解決掉。


2、分支:實質上是為了更多的人並行工作,而出現的概念。當然,這一概念,需要版本管理工具的支持。


在某個版本發布之後,並不意味著這一版本已經完美無缺,所以,我們需要維護一個分支,在其中只添加 bugfix 類的改進,而不會增加新的功能特性。


而另一方面,我們會有一個 master 分支,開發人員可以盡情先把功能特性提交上去,而不必太過顧慮產品的穩定性。


在人數更多的時候,我們會創建更多的分支,比如:一個大項目組,可以分為 3 個小組,每個小組有一個自己的分支,他們先在自己的分支上工作一段時間。然後再將這一個小組的工作,批量匯入主幹分支。



在工具改進的過程中,工作流程也在改進,起因還是因為人容易犯錯誤,在開源社區,這樣的問題尤其突出。如果是在公司裡,大家都是抬頭不見低頭見的同事,當初也是經過足夠的面試,具備基本的能力,才能進來的。但是在開源社區,一個從來沒有見過的 ID 號,想要向我的項目提交代碼,我怎麼可能放心?


因此,在開源社區最初的形態:mailing list 中,就已經形成了一套行之有效的代碼提交規範。


想要向某一個項目提交自己的代碼,首先需要訂閱那個項目的郵件列表,跟裡面的 committer 混個臉熟。提交代碼,其實就是發一封郵件。在郵件裡,要清楚地介紹自己打算幹些啥,簡明扼要,而且最好不要一下子就「搞一個大動作」。一開始,大家都不熟,你上來就想要貢獻一個「幾千行代碼的大特性」,誰都沒法信任你。


最好是從 bugfix 開始,所以那些代碼貢獻,都被稱之為補丁 (patch)。一個補丁,最好不要太大,幾行(最多幾十行),這樣那些大牛們才會有心情 review 這些代碼。


因為,實際上只有他們才有資格向代碼庫提交代碼,所以:他們才被稱之為 committer。所以,我查看提交日誌的時候,會發現兩個屬性:author (實際寫這段代碼的人)以及 committer (將代碼提交到代碼庫裡的人)。


而這樣的工作模式,就被稱之為 code review。隨著開源社區的日益成熟,開源社區的這種工作模式,也開始進入企業,在企業內部貫徹 code review 的工作流,也變成了一種常態。



隨著團隊數量的進一步上升,僅僅依靠人類肉眼審查代碼,想要杜絕各種錯誤,其實是不可能。這時候,工具的作用再一次體現出來了。


如果一個工作,實際上是一種簡單重複勞動,那麼:就可以通過編程,將他自動化完成。例如,自動化編譯、自動化測試。


如果一個工作可以自動化完成,那麼:我們完全可以將這個工作分解得更加細緻。例如:從自動化的驗收測試,到自動化的單元測試。


如果我們可以在一個工作的各個環節都執行檢查,那麼:我們完全可以自動化地檢查所有可能檢查的部分。例如:我們不僅僅可以檢查功能,還可以檢查語法,可以檢查編程規範,檢查是否存在安全隱患等等。


如果我們可以自行一次自動化檢查,那麼:我們完全可以更加頻繁地執行這樣的檢查。例如:開發者的每一次提交,都能夠觸發一次自動化的檢查。


最為理想的開發流程是:所有的開發工作,都能夠各自獨立進展,互不幹擾。最好是每一個特性、每一個 bugfix,都有一個獨立的分支。然後,在自己的分支上,完成一套自動化檢查。再將這個分支合入主幹,再跑一遍全套的自動化檢查。這樣,我們就能知道:這一項工作確實已經完成了,而且沒有破壞任何其他的部分。


當然,事情並沒有那麼簡單,如果是小型項目,那麼每次 CI 的成本,都會非常低。速度也會快到忽略不計。但是,一旦項目變得複雜,代碼庫變得龐大,編譯與測試的時間以小時來計算時,當開發者數量增長,並發提交的人數,超過並發 CI 的伺服器數量時,問題就會複雜到專門寫一本書了。



如果 Linux 的開發者,不是成千上萬那麼多,也許 Linus 當初也不會選用 BitKeeper。當然,也不會因此出現各種風波,最後讓大神在一怒之下,10 天時間,自己擼了一個 Git 出來。


相對於 SVN,Git 有一些特別明顯的好處:


分布式配置庫,支持離線工作,保存各種提交歷史。而且,在不存在中心倉庫的情況下,任何兩個 Git 倉庫之間,可以交換代碼。


更好的分支模型,使得創建一個分支,合併一個分支,快捷高效。當一個團隊的人數越來越多,代碼越來越複雜時,使用 SVN 分支所帶來的煩惱,就會迫使他們最終選擇 Git。


Git 有一個複雜的由 commits 組成的 DAG(有向無環圖),這樣一種數據結構,能夠更加準確的記錄實際開發過程中的各種狀況,尤其是在用到 rebase、cherry-pick、three-way merge 的特性時,會感覺非常自然。


當然,有很多不必面對這些複雜性的軟體項目,會感到 Git 過於複雜,難以理解,而且沒有必要掌握。至於那些的確需要創建諸多分支,的確存在多種代碼合併的情況,的確需要更加頻繁的運行自動化測試的團隊,選擇 Git,就會非常自然。



當出現了 Git 這樣的工具之後,我們會發現世界並沒有變得更加美好,因為一個常見現象:過於靈活的工具,會讓人更加容易犯錯。在項目組完全使用 Git 的情況下,依然可以設計出多種多樣的工作流程。


最簡單的一種:每個人有自己的 Git 倉庫,然後各自多加幾個 remote,然後隨意地傳來傳去類似於 SVN 的集中工作流程,大家都向同一個中心倉庫提交代碼集成管理者工作流,貢獻者將代碼推送到各自的公開倉庫,然後給維護者發送郵件,請求拉取自己的更新,最後由維護者手動完成合入司令官與副官工作流,在 Git 官方網站的介紹中,描述到:「一般擁有數百位協作開發者的超大型項目才會用到這樣的工作方式,例如著名的 Linux 內核項目」。


在 Git 出現(2005 年)之後的幾年裡,陸陸續續出現了一些新的創造,較為突出的有兩個:Github(2008 年)、Gerrit(2008 年)。這兩個工具,本質上都是對於過於靈活的 Git 工作流程進行限制、簡化以及優化。只不過兩種方案的出發點,大不相同,導致其產品設計與功能特性,也有了諸多區別。


Github 的出發點是大量中小型開源項目的託管服務,而且,為了形成一個完整的大社區,Github 在社交化方面,投入了大量的精力,也創造了諸多世界第一的奇蹟。


至於 Gerrit 的出發點,這是大型複雜項目的 Code Review 管理。從誕生之出,Gerrit 就是為了像 Android 這樣的大型項目服務的。通常一個 Gerrit 實例,只服務於一個大項目。對於構造一個社區,形成某種跨項目的開源生態圈,Gerrit 並無興趣。



很多時候,我們會發現這樣的現象:研發工具的演進與開發模式的演進,往往呈現一種交互影響的關係。複雜的開發模式,會促使新工具的誕生。而新工具的引入,也會促使傳統的開發模式,發生變革。


在本文的前半部分,我們主要探討的是各種需求複雜化之後,如何催生了一代又一代的新工具。而另一方面,當團隊引入一種新工具之後,常常會發生的,並不是 happy ending。


一些問題的確被解決了,但是新的問題又產生了。樂觀的說,我們會發現新工具的各種能力,經過巧妙的組合,產生新的用法,甚至遠遠超過工具設計者的設想。悲觀的說,我們也會發現新工具的各種強大能力,在尚未熟練掌握的人手裡,會產生各種意想不到的災難。


在那些較為積極進取的團隊中,新工具往往會成為某種催化劑,他們會迅速上手,然後越玩越好。於是我們最終會發現,一切問題,究其根本,還是人的問題。


人、工具與流程,是項目管理中的三大要素,而其中人是決定因素。對於管理者而言,是否能夠正確的判斷問題出在哪裡,以及通過何種手段去解決,是最為重要的。我們經常會遇到這樣的管理者,在遇到麻煩時,習慣性的選擇某一種手段:有些領導特別喜歡「制定管理規範」、有些領導特別喜歡「採用先進的工具」、還有些領導特別喜歡「給員工打雞血」。我們並不能簡單地說他們做錯了。但是:只會單一手段的領導,通常更容易犯錯。


總而言之,在軟體開發的過程中,為目前的團隊選擇合適的工具,並且既不保守、又不冒進的選擇某種新的工具,而且還能夠帶領整個團隊,用好這些工具。的確是極大的挑戰,也可以說是沒有終點的旅程.



華為公司內源社區平臺架構師;開源社理事


1997 年畢業於華東師範大學,曾任盛大創新院的高級研究員、印客網的技術總監。多年來一直在編程的第一線,並以 Coding 為最大的樂趣。著有一本電子書《開源思索集》,在豆瓣、簡書、亞馬遜、多看閱讀等平臺均可以直接下載。目前專注於華為內源社區的建設。


微信公眾號中回複數字查看更多精華文章:


回復【1】:技術乾貨

回復【2】:程式設計師幽默世界

回復【3】:物聯網江湖

回復【4】:華為招聘

回復【5】:HDG 視頻+PPT 匯總

回復【6】:華為開發者大賽獲獎作品展示


相關焦點

  • 聊聊Deno的那些事
    👆  這是第 99 篇不摻水的原創,想要了解更多,請戳上方藍色字體:政採雲前端團隊 關注我們吧~本文首發於政採雲前端團隊博客:聊聊Deno的那些事https://www.zoo.team/article/talk-about-denoDeno 是什麼Deno 是一個簡單、現代、安全的 JavaScript、TypeScript、Webassembly (https
  • 聊聊前端排序的那些事
    在這樣的背景下,前端排序這件事其實取決於各家瀏覽器的具體實現。那麼,當今主流的瀏覽器關於排序是怎麼實現的呢?接下來,我們分別簡單對比一下 Chrome、Firefox 和 Microsoft Edge。Chrome中的實現Chrome 的JavaScript引擎是 v8。由於它是開源的,所以可以直接看原始碼。
  • 聊聊H5上點擊事件那些事
    下面我們就來講講點擊事件那些事。點擊事件的觸發順序一次DOM點擊事件的觸發過程:觸發touchstart事件觸發touchmove事件觸發touchend事件觸發click事件然後因為存在事件冒泡的存在我們的點擊事件會向父節點傳遞,如果父節點也綁定了點擊,則也會觸發父組件的點擊事件。
  • 腦洞:一次代碼提交,原來還可以……
    每天的Git代碼提交和注釋作為技術開發人員,每天在開發工作中,都需要時不時或頻繁地提交修改代碼到Git倉庫,同時編寫提交注釋。
  • 從日本昭和時期聊聊電飯鍋的那些事
    那麼趁著這個機會呢,和大家聊聊電飯鍋的那些事。
  • Git如何提交代碼
    git學習篇(2)這是學習Git的第二篇筆記,今天來講講Git提交代碼的使用命令。
  • 一起聊聊論文那些事兒!
    今天就和大家聊聊論文那些事兒!     最近,不少同學開始苦惱於自己的畢業論文開題了。你知道哪些奇葩的論文選題嗎。別人家的論文選題就是不一樣!    不是充滿了一股」味道「,就是考驗肺活量,要不然就是和動物槓上了。不過就衝著這些研究者的」好奇心「,也要為他們的研究點讚!
  • 黑龍領主加入風暴英雄大家庭,聊聊大表哥的那些事
    這個大傢伙,為何擁有如此巨大的魅力呢,下面我們就來聊聊死亡之翼的那些事。在東方文化中以龍比作皇帝,以龍作為圖騰;而在西方文化中,龍族更是充滿著力量與強大的代名詞。而以「死亡之翼」來命名的這隻黑龍顯然更是其中的佼佼者。這不過這份力量帶給艾澤拉斯大陸的卻是傷痕與毀滅!很難想像的是,這樣一支以死亡為名的龍族,曾經也是艾澤拉斯的守護者之一。
  • 來聊聊屏幕色域那些事!
    今天,惠課廳君就跟大家嘮一嘮屏幕色域那些事!對顯示器素質要求比較高的用戶來說,一塊好的屏幕是一臺好電腦的必備素質。所以,今天我們來聊聊關於色域的三個問題:色域是什麼?都有哪些常見色域?色域之間可以換算嗎?
  • PHP表單提交
    今天我們來聊聊在php裡邊如何將網頁數據提交給php接收!<td><input name="email" type="text" id="email"/></td> </tr> <tr> <td colspan="2" align="center"><input type="submit" value="提交
  • 【老徐專欄】聊聊海底電纜的那些事
    聊聊海底電纜的那些事在世界大洋之下,鋪設有55萬英裡長的海底光纜。根據One Earth Future基金會Stable Seas項目的報告,海底網絡承擔著全球洲際通信業務的97%,每天傳輸價值1000萬美元的金融交易數據、每天完成價值10萬億美元的交易。
  • 巧用 gitHooks 提交前校驗代碼
    ,git commit -m 'test'就會發現 eslint 代碼檢查通過了,能正常提交了,以上實踐能很好解釋 commit 前怎麼檢驗代碼,但是有個缺點就是別人 pull 你的代碼要執行git config 'core.hooksPath' .customGitHooks能起作用;下面就介紹 husky,lint-staged,commitlint 的使用.git 文件夾不會被跟蹤並且上傳至遠程倉庫的
  • 歐式麵包大全來也,聊聊歐包那些事!
  • 聊聊中國挖礦的那些事
    2009年,一個叫中本聰的日裔美國人發明了比特幣,它是一種開原始碼的數字貨幣。大多數人聽到數字貨幣這個概念第一反映就是太虛了,既不是黃金本位,也沒有政府背書,萬一突然有一天所有人都不認了,我買進去的錢不是日了狗了?
  • 說說代碼質量、代碼安全和軟體測試那些事
    今天,就和大家簡單聊聊代碼質量、代碼安全和軟體測試的話題。 有關代碼質量,我會藉助 Sonar 這樣的工具,將其納入代碼質量和代碼規範管理,這對自研產品和外包項目質量把控都非常重要。快速體驗下 Sonar,可以這樣,克隆 Open Testng Suite,然後運行 mvn 命令
  • 你見過最奇葩的代碼提交信息是什麼?別再為寫commit message頭疼了!
    寫在前面對一個developer來說,有時候變量命名,提交代碼時的提交信息會讓人很頭疼,本文主要聊聊怎麼優雅的書寫
  • Linux工作坊,資深創客跟你聊聊Linux那些事
    本次工作坊,帶你了解linux的「八卦」,動手在虛擬機安裝debian,實操日常套路,最後聊聊raspberry pi。        比較有代表性的課程有《從代碼到實物:造你所想》、《自行車旅行之道》、《重構跨界視野、共創智美未來》、《智能產品設計》等。      2014~2019年,在西南地區引入並組織中美青年創客大賽。2018年獲國家教學成果獎二等獎,四川省教學成果一等獎。
  • 你提交代碼前沒有校驗?巧用gitHooks解決
    ,git commit -m 'test'就會發現 eslint 代碼檢查通過了,能正常提交了,以上實踐能很好解釋 commit 前怎麼檢驗代碼,但是有個缺點就是別人 pull 你的代碼要執行git config 'core.hooksPath' .customGitHooks能起作用;下面就介紹 husky,lint-staged,commitlint 的使用.git 文件夾不會被跟蹤並且上傳至遠程倉庫的
  • 關於卡貼機的那些事
    今天小編就帶大家來聊聊卡貼機的那些事由於我們國內運營商跟國外運營商不太一樣。國外的運營商為了拉攏客戶,佔領市場,推出了一些所謂0元購機或者9.9元購機。
  • 別亂提交代碼了,看下大廠 Git 提交規範是怎麼做的!
    項目內安裝commitlint & huskyCommit message規範在rrd-fe落地使用情況擴展閱讀git是現在市面上最流行的版本控制工具,書寫良好的commit message能大大提高代碼維護的效率。但是在日常開發中由於缺少對於commit message的約束,導致填寫內容隨意、質量參差不齊,可讀性低亦難以維護。