2021-05-12 14:32:11
基於 GitLab 的團隊共同作業模式 - 前生篇
題註:
在 eggjs 團隊的日常共同作業中,深度依賴於「基於 GitLab 的一站式硬碟式非同步共同作業模式」。
本文作為相關介紹文章第一篇引子,轉自阿里內部,已獲作者 @晚學 授權。原文標題:「我是這樣開始用 Git 的」
前言
如果這篇文章以 「Git 好用到沒朋友,甩 svn 十條長安街」的基調開始,中間插上一大段從網上抄來的、已經被轉載得滿地球都是的、看著特有道理但自己看完卻完全沒感覺的文字,末了結尾處高喊 Git 我愛你並且自作多情的留下 6 個亢奮的感嘆號的話(籲……先喘口氣),那麼,這篇文章肯定收了錢了。
我們以碼字為生的文字工作者最重要的精神就是:冷靜並客觀。
所以今天,我們就冷靜並客觀的來看看 svn 和 Git,看 Git 是不是後生可畏,看 svn 是不是老當益壯。
入門總是伴隨著慘不忍睹
可能大部分人跟我的經歷是一樣的,最先接觸到的 VCS(version control system)是 svn ,然後為了不被人家說土,開始嘗試認識 Git。
如果把 svn 和 Git 比作朋友的話,他倆可謂性格都非常分明,svn 是個直腸子,簡單直接,從不繞彎彎,svn 命令語意非常清楚,如果你不是高階 SCM ,你只要學會:
svn checkout
svn update
svn commit
svn revert
大概你就能夠和別人進行共同作業開發了,你看,多簡單。
但 Git 不一樣,他可不是個隨和的朋友,他比 svn 有個性太多了,相信大部分開始學習 Git 的人都曾經被這句話搞到懷疑自己的智商以至放棄 Git -- Git 是一個分散式的版本管理系統。
一開始你感覺是這樣的:我勒個去,分散式,很高階啊,哥得看看。
看了半天,你心裡打鼓了:矮油我去,看了半天命令有點蒙圈,不過還是能夠清醒的認識到自己完全沒理解 「分散式」這三個字用在 Git 裡面是個什麼意思的。
再回過頭去看看 Git 命令,你會堅定的認為程式碼的歸宿就應該是 svn,Git 搞那麼複雜是在秀智商麼?滾蛋,一邊玩去。
但是當你聽到外面有人不斷的說:“Git 太特麼好用了,簡直神器” 之類話,你又開始懷疑自己:是我太笨還是這個世界太荒唐?
我就是這麼一路走過來的。
實際上...
實際上,svn 和 Git 只是兩個不同的東西而已,Git 沒有比 svn 好到天翻地覆,svn 也沒有人們嘴裡說的那麼不堪。
作為工具來講他倆都專注的做一件事情:版本控制。最大的差別就是這個所謂的 「分散式」,那麼這個分散式到底是個什麼鬼?
svn 的架構我們都很熟悉了,經典 CS 架構:某個地方 run 著一個 svn server,上面存放著很多程式碼倉庫,所有人通過 svn client 和 svn server 進行互動:拉取程式碼、提交程式碼、更新程式碼。一切都是那麼的自然。
Git 號稱分散式的意思是說 “在某個地方 run 著很多 git server ” 麼?如果是這樣的,好像也沒什麼稀奇的呀,相信 svn 也能做到。
實際上……所謂 Git 分散式版本控制和 svn 傳統版本控制的區別是這樣的:
- svn 模式:本地檔案 → svn 遠端版本控制伺服器
- Git 模式:本地檔案 → 本地版本控制“伺服器” → Git 遠端版本控制伺服器
差別就是 Git 在你本地多做了一次版本控制,相當於在你本地有一個 svn 伺服器,遠端還有一個 svn 伺服器,那麼為什麼要這麼做呢?原來 svn 那種直觀的模式不是挺好的麼?
實際上……原因很簡單,我們來看一個故事,這樣的場景每天都在上演:
有一個專案,需要 10 個人一起共同作業完成。
-
v0.0.1 的時候:大家用 svn ,新建了一個叫 XX-v-0.0.1 的倉庫,所有人都往這個程式碼倉庫裡面提交程式碼,久而久之大家發現,別人提交的老是會影響到自己(就是衝突啦),自己提交的也會影響到別人,人數越多這個影響就會被放的越大,甚至有時候由於一個人的失誤提交導致大家都沒法工作了,如果這種“失誤”每天多發生幾次,基本上就沒什麼心情寫程式碼了。
-
v0.0.2 的時候:大家開始總結經驗,不能這麼搞了,所有人從 XX-v-0.0.2 的程式碼倉庫上建立一個自己的分支,自己開發,然後每天我們找個時間坐在一起,一個一個的把自己的分支合併到 XX-v-0.0.2 上面。這種做法某種程度上緩解了 0.0.1 版本的時候遇到的問題,其實就是把衝突的頻率降下去了而已,實質跟 0.0.1 的做法沒有任何區別。(試想一下假如還是在同一個分支上,大家約定都不提交,每天找個時間坐在一起一個一個的提交,是不是效果一樣一樣的?前者唯一的好處就是自己的程式碼起碼有個版本庫管著,不至於本地丟了就全沒了;但是前者一個典型的壞處就是到合併的時候如果差異特別大的話合併起來就會相當困難,甚至完全沒法合併。)
0.0.1 的做法是高頻衝突概率,但是每次衝突的解決成本相對較小
0.0.2 的做法是低頻衝突概率,但是每次衝突解決的成本相對較高
沒法玩了麼?
上述情況的排列組合裡面有這麼一個看起來最優的組合:如果我能做到衝突的頻率很低,並且衝突解決的成本也低,那豈不是達到了一個比較完美的狀態?
要想做到 「衝突頻率低」,那麼只能限制提交的頻率,怎麼限制?如果都在一個分支上搞,你總不能發個紅標頭檔案限制每個人每天提交的次數吧?那就在各自分支上搞唄!提交的次數我不能限制,合併的次數我還是可控的吧?搞定!所以結論是用分支分開搞比大家攪在一起搞要好。
要想做到 「解決衝突成本低」,怎麼搞?順著上面的分支開發思路,要想成本低那就得經常合併啊?三個和尚就沒水吃了,更何況是十個程式設計師,怎麼約定誰先合併誰後合併?
乾脆我們找一個人專門來做合併,這個人就是 SCM ,SCM 每天就合併程式碼玩兒,第一個把 A 分支的程式碼合併進主幹,問題不大,第二個把 B 分支合併進來,稍微有點費勁(因為差異變大了,可能會有衝突),第三個把 C 分支的程式碼合併進來,比較費勁(差異又增大了,衝突會增多),第四個把 D 分支的程式碼合併進來,就很困難了,第五個把 E 分支的程式碼合併進來.... SCM 離職不幹了。
這是一個悲慘的笨 SCM 的故事。
後來來了個聰明的 SCM ,他合併完A分支之後,告訴剩下的 9 個分支 owner :
你們把主幹程式碼和自己的程式碼先合併一下,誰先合併完誰先找我,我優先幫他合併進主幹。
於是聰明 SCM 把以前笨 SCM 自己幹的活兒分到了 9 個人頭上,顯然輕鬆了許多。但是程式設計師不樂意了:
憑啥寫程式碼的也是老子,合併的也是老子,你知道合併有多麻煩麼,先 diff 倆分支,拿到 diff 檔案,再 patch 到我自己的分支上,解決完衝突連廁所都不敢上趕緊一路小跑跑去找你 SCM 大人,我特麼累不累啊!!
聰明 SCM 說:
大哥你別急,你們忙我也沒閒著,我做了一個工具,特意取了個名字叫 Git,洋氣吧?你只要執行一個命令(git rebase 主幹)就自動把主幹程式碼合併到你的分支上去了,有衝突就解決,沒衝突最好。
到這個時候為止,雖然不能說皆大歡喜,至少我們的目的達到了:
- 分支開發,大家減少“衝突頻率”
- 經常性的合併,並且藉助工具減少 SCM 和程式設計師的工作量,大家都省事兒
但是,不優雅。
聰明 SCM 想:
所有人都建分支搞,搞得 svn 上一坨一坨的分支,眼花繚亂的亂死了,這不是增加我的工作量麼,其實這個分支對於開發者來講,就是用於版本控制的,你放在你自己本地不行麼?當你要合併的時候你再把這個分支給我,這樣咱們公司的版本庫 server 上不也乾淨麼?這些臨時的程式碼分支不要留在上面,多礙事。那麼怎麼放在本地呢?很簡單啊,你自己在本地搭一個 svn server ,你自己的分支就在自己本地搞,你自己專屬的 svn 伺服器隨便怎麼搞都無所謂,然後等你要提交上來給我合併的時候,你再把這個分支提交到公司的 svn server 上來,別擔心,還記得我那個洋氣的工具麼? Git !我又給他加了一個功能,幫你區分提交到不同的伺服器,你看啊,你提交你自己原生的,我叫做 git commit ,你把你原生的提交給我的,我叫做 git push ,你看,多合理,push 就是 push 我趕緊幫你搞合併吶,為了取這名字我操碎了心吶,你說我怎麼這麼有才呢?
好,故事講完了,多麼自然的,“雙 svn 架構” 就演變成了今天的 Git,它很好的解決了我們遇到的問題:
- 極其方便的分支功能(而且是精明的在你本地開分支),讓開發者很方便的在分支上開發,其背後的良苦用心在於借助分支幫大家 “降低衝突頻率”。
- 極其方便的 rebase 和 merge 功能,在 “經常合併” 的思路下,既解放了 SCM ,又解放了開發者,其背後的深意實則是鼓勵大家 “經常合併”。
這個時候,你應該能理解為什麼大家都說 Git 洋氣了吧?也大概能理解 Git 的一個歷史演進過程了吧(咳咳,這個過程是我自己總結和理解的哈,反正我是這麼理解的,也不知道對不對,管它呢,聽起來還是能自圓其說的)
好,到這裡,你估計不得不承認 Git 確實比 svn 更先進一些,不過你依然無法抵擋 svn 簡單好用的誘惑,沒關係,如果 Git 就此止步,那它頂多也就是個“略牛逼”的軟體而已,掀不起什麼風浪的。
基於 Git 有個叫 GitLab 的開源軟體,已經被部署到了阿里,它才是利器。
GitLab
如果說 svn 是軟體,有了 GitLab 我們擁有的就是項服務了。
就像 Hadoop 是一個軟體,阿里雲是一項服務。
站在使用者的角度上來講,服務顯然要比軟體來的方便的多得多,服務除了包含軟體本身之外,還包含周邊很多的東西,裝逼的時候,我們通常管這些 “周邊的東西” 叫「生態」。
不假大空,我們還是從身邊活生生的例子來剖析,一個軟體的生命週期,通常我們為了保證軟體的品質會做這麼幾件事情:
- code review
- 持續整合
- 需求管理
- 缺陷跟蹤
-
在 svn 系裡面,如果我們想要做 code review,我們得自己搭一個服務叫做 reviewboard( rb 的確是一個值得尊敬的牛逼軟體,但是我們得自己維護這玩意多少就有些不好玩了)
-
在 svn 系裡面,如果我們想要做持續整合,我們得自己搭一個軟體叫做 buildbot 或者 jekins( buildbot 和 jekins 的確是值得尊敬的牛逼的軟體,但是我們得自己維護這玩意多少就有些不好玩了)
-
在 svn 系裡面,如果我們想要做需求管理,我們得自己搭一個軟體叫做 jira 或者其他什麼的( jira 的確是一個值得尊敬的牛逼的軟體,但是我們得自己維護這玩意多少就有些不好玩了)
-
在 svn 系裡面,如果我們想要做缺陷管理,我們得自己搭一個軟體叫做 bugfree 或者其他什麼的( bugfree 的確是一個值得尊敬的牛逼的軟體,但是我們得自己維護這玩意多少就有些不好玩了)
我勒個去,等會等會,我平時還真沒注意,一個 svn 周邊要自建這麼多東西啊???
------------------------------------------------
沒錯,這就是軟體時代的玩法,嘿嘿,不過到了服務時代,完全就不一樣了,GitLab 讓你爽到沒朋友。
以上所有的這些功能型軟體,GitLab 全部包含,重要的是你不必跨多個系統去使用,在 GitLab 上,所有的事情全部一站搞定。
提供給程式設計師的服務,如果能夠做到不轉移、不分散他們的注意力,就是積了大德。
GitLab 做到了,一切以程式碼為核心,圍繞在程式碼周邊的是:需求(issue)、持續整合(gitlab-ci)、code-review(原生態天然自帶功能,非常自然)等等
------------------------------------------------
一個有意思的現象是:程式設計師在 “需求管理平台”、“缺陷跟蹤平台” 等這些平台上毫無熱情,卻在 GitLab 上能思維敏捷、口齒伶俐、口吐蓮花、舌戰群儒,為啥?
很簡單,程式設計師離不開程式碼就好像農民離不開土地一樣。
別裝了,那是因為 GitLab 是一個社群,你在上面騷浪賤能引起關注、引發討論,你在“需求管理平台”上寫個萬字長文看有人理你麼。。。
好了,也不早了,這個萬字長文也該發到 GitLab 上找找存在感了。
對了,最後,我們客觀並且冷靜的得出一個結論:Git 來了,可以讓操勞了這麼多年的 svn 休息休息了。
下回,考慮來一發技術流的文章,來好好扯一扯 svn 的命令和 Git 的命令,相信在這篇文章的基礎之上,再去理解 Git 命令就沒那麼困難了。
更多GitLab相關教學見以下內容:
Ubuntu 14.04下安裝GitLab指南 http://www.linuxidc.com/Linux/2015-12/126876.htm
如何在Ubuntu Server 14.04下安裝Gitlab中文版 http://www.linuxidc.com/Linux/2015-12/126875.htm
CentOS原始碼安裝GitLab漢化版 http://www.linuxidc.com/Linux/2015-10/124648.htm
CentOS 7下GitLab 9.1.0 安裝及漢化 http://www.linuxidc.com/Linux/2017-04/143240.htm
搭建屬於自己的GitLab http://www.linuxidc.com/Linux/2017-04/142665.htm
Ubuntu 14.04搭建GitLab伺服器 http://www.linuxidc.com/Linux/2017-02/140959.htm
CentOS 6.5安裝GitLab教學及相關問題解決 http://www.linuxidc.com/Linux/2014-05/101526.htm
升級GitLab到8.2.0 http://www.linuxidc.com/Linux/2015-12/126220.htm
相關文章