標籤:

如何理解 Git 的分散式?

很多關於 Git 的文章都會說 Git 是分散式的,比 SVN 那種集中式的管理更安全。還有一種說法是,可以在火車上 commit 代碼。

我的疑問是:SVN 之所以集中管理,一定程度上是需要避免代碼的衝突,而 Git 這種所謂的離線提交,等到聯網 push 的時候不是也會衝突嗎?從這個角度來看,離線與在線提交都會產生代碼衝突,那為什麼 Git 就好,SVN 就不好呢?


首先,衝突是無法避免的,Git並不能減少衝突,任何其他的VCS(VSS這種不算)也不能。

個人覺得Git相比SVN,主要有以下幾點:

1. 去中心化

這個應該就是樓主所說的分散式。Git是沒有中心伺服器的,每個人機器上都是一個完整的庫,我們平時開發代碼時的中央伺服器其實和我們自己機器上的庫內容是完全一樣的(格式有點不同,是bare的)。雖然平時大家都是將代碼提交到中央伺服器上再統一pull別人的代碼,但實際情況你可以總是pull張三的庫,然後push給李四等等操作。

個人認為去中心化是Git(也包括其他分散式VCS)最偉大的改變。去中心化意味著沒有權威、沒有主力,所有人都是平等的。這概念本身看起來好像沒什麼,但實際對社區影響是巨大的,去看看 http://github.com 上的fork功能,你可以fork任何一個你喜歡的項目,接著按自己的喜好修改成自己的項目,或是發起pull request請原作者merge你的功能到他們項目里去(這同樣也得益於Git另一項與SVN很大不同的功能——分支策略),而且大多數開源項目都會鼓勵你去fork它們。這裡面沒有權威,沒有主從,所有人只要有興趣都可以在其他人的基礎上去構建更強大或是更有領域針對性的項目。大家不是為了開發某個項目而來,而是為了貢獻更強的功能給社區,這樣最終的項目將是整個社區所有人共同努力的結果,將生生世世繁衍不息。

當然,去中心化也可能會引發一些問題,比如Linux的各種發行版本有時候讓人難以抉擇,但相信市場之手會幫我們做出選擇。

2. 本地提交

本地提交好處主要有3點:

1) 斷網提交

2) 小步提交。可以對自己的階段成果有跟蹤,並且提高每次變更的安全性

3) 本地庫。這個和斷網提交是同一個實現,但從需求角度出發則略有不同,主要是說即使只有自己一個人開發項目,也可以輕易的讓自己的代碼有版本跟蹤,而不需要去費力建個什麼svn server

4) 本地回滾。這個其實是由於本地庫的存在而產生的,但可以減少中央庫上的冗餘版本

3. 分支策略

分支策略從技術上來講是將版本節點化了,即最終的版本狀態是樹狀的。從結果上來講既是弱化了分支,也是強化了分支。弱化的是分支的概念,強化的是分支的功能。

在Git實際開發中分支的分離和merge是屬於日常操作,開啟和合併分支成本相比SVN要小得多:SVN是複製一份代碼到分支目錄,Git則是在分支點做一下標記。隨便一次衝突就會自動產生分支,所以大家每天都在與分支打交道。這便是弱化了分支的概念,由於分支成本很小,因此使得按功能分支的開發模式(每個分支一個功能,開發完了再merge到主幹)變得非常簡單,大家可以完全不需要再因為擔心SCM成本太高而選用主幹開發模式(所有功能都在主幹上開發,到了發版本前再分離出分支)。

當然Git還有很多其他不錯的地方,比如Tag策略(和分支策略一樣,做個標記,不像SVN要複製一份過去),下載時會壓縮以加快速度,各類提示非常到位


無論是 svn 還是 git 的工作流,都是在本地解決衝突再提交,而不是在提交時解決衝突的。所以:

svn 的模式是:

1。寫代碼。

3。從伺服器拉回伺服器的當前版本庫,並解決伺服器版本庫與本地代碼的衝突。

5。將本地代碼提交到伺服器。

分散式版本管理的模式是:

1。寫代碼。

2。提交到本地版本庫。

3。從伺服器拉回伺服器的當前版本庫,並解決伺服器版本庫與本地代碼的衝突。

4。將遠程庫與本地代碼合併結果提交到本地版本庫。

5。將本地版本庫推到伺服器。

所以,分散式版本管理僅僅是增加了本地庫這個概念,其餘的概念與集中管理並無區別。——但是 svn 在與伺服器同步之前無法提交代碼,因而本地修改更容易出問題。


所謂集中式版本控制工具,總有一個中心伺服器,提供一個項目倉庫,大家的代碼的提交都是統一提交到這個中心伺服器上的。 而分散式版本控制工具類似Git,可以有多個代碼倉庫,比如可以在本地。同時它可以方便的進行代碼倉庫合併。

分散式的好處在於可以脫離中心伺服器進行代碼的版本控制,而不在於沒有衝突。基於共享合併模式的版本控制都不可避免的會有衝突的。


分散式和 branching 沒有關係。Perforce 和 ClearCase 都有 branching 功能,但是它們都有中央伺服器。由一個節點來負責裁斷 branching 和 merge 中產生的競爭問題——比如 lock 某個節點禁止 merge。而且一般情況下集中式管理,所有的 branch 都放在一個 storage 上。如果這個 storage 產生問題所有數據都會丟失。

git 是整個代碼庫可以以 branch 為最小單位分隔 storage。branching 和 merge 只需要涉及相關的 storage。


我覺得要深入理解Git,還是得看源碼。相較於其他的(如 svn,甚至 hg),我覺得 git 的實現更像一個 file system,從裡到外(或從上到下)的幾個設計層面來看都是 symlink 和 data blob 的結構,這點是我認為和其他 VCS (SCM) 的本質區別可能是這樣,加上早期使用者僅限於開發者的情況,git cli 設計有明顯的 leaky abstraction,即必須知道具體實現,才能理解和正確使用本來應該為 blackbox 的各種 subcommand

因此我認為,要會正確使用並用好 git,恐怕沒有捷徑可走,只能從理解 git 的實現原理開始,即什麼 data blob 和 tree 等(這也是大多數 git 書一上了就介紹 git 的底層存儲方式設計的原因),然後才是 DVCS 的基本原理,即在 DVCS 中歷史是 directed acyclic graph。


首先,思考一下CVS和SVN的缺點,只有一個中心伺服器,通常都架在內網,

如果是在外出差要改代碼,就麻煩了,需要VPN訪問公司的區域網,才能commit代碼,查看log等,如果沒法連接網路,或者沒有VPN,則很難和公司的同事協同工作。

而git如何解決這個問題呢?

出差時clone一下,完整倉庫就存在你的機器上了,

不需要連接伺服器,可以任意commit開發,查看log了,

在分支里開發,就算主分支有更新,也不影響當前的工作進程,

需要將更改更新到公司中心伺服器?可以通過patch的形式通過郵件或IM共享,由在公司辦公的同事應用patch更新倉庫,不需要VPN,不需要VPN


最大的區別在於GIT網路中任意兩點可以交換 代碼,舉個例子。 假如剛開始用SVN, 開發 人員A和B都向SVN server C提交code。這種 模式大家應該很熟悉。請問這個時候,A和B 可以私下交流代碼嗎?

svn明顯不行,而git可以。開發者B可以隨時 獲取A的代碼(注意是直接向A獲取,而不是 向git central server獲取)。反之A也可以隨 便獲取B的代碼。

這是我理解的GIT分散式。


按我的理解,git的分散式是一個實現細節。

git的設計目標是要讓各種操作,比方說開新分支變得無比的快。要快,在目前的技術條件下,那就只能是把所有的數據都在本地放一個備份,這樣才有可能在本地完成所有操作 -&> 所有的操作都可以很快。

git是為了操作快,選擇了分散式。

然後,是的「離線與在線提交都會產生代碼衝突」,這個問題,跟系統是分散式還是集中式無關。而其它的所有「分散式」帶來的功能特性,其實集中式也是可以做到的,只是操作起來不夠快而已。


我覺得,Git更重要的在於讓更多的人一起開發。SVN你每次提交的時候伺服器都要檢查是否你已經更新到最新版本了,這樣避免衝突,但是如果上萬人一起在開發,就會發生大家一起爭搶。Git就是為了解決Linux這樣的系統開發時所遇到的問題。

比如SVN里你想增加一個新功能,開一個分支的時候,所有人都可以看得到這個分支,而其他人是和這個分支無關,不需要知道這個分支也不需要下載這個分支。Git里你可以自己在本地建立這個分支,調好了以後再往父級或爺級分支合併。

舉個最簡單的例子,假如兩個人同時在開發兩個不同的新功能,SVN需要你每完成一小步,就要去合併到伺服器一次,而Git則可以兩個人分別完成各自的工作以後,再把兩個長長的分支做一次合併。

所以,我覺得SVN只適合很小的項目,或者只有一個人開發的項目,其他都應該用Git。


你需要先明白git的歷史,git的初衷僅僅是為了解決Linux內核多人開發時的分散式需求。而svn是集中式的,svn必須要有個伺服器代碼才能提交,而git沒有伺服器器也可以提交給本機(本機就是一台伺服器)。

其實,你參加過Linux內核開發的話,你會發現你想把你的代碼貢獻出來被作者Linus採用的話,你需要把代碼通過電子郵件傳給他,而不是通過push之類的命令。

你的提問說明你對git的歷史還不清楚,推薦你看這個網頁http://www.qllm.tech/git.shtml


如果svn的衝突是小孩打架的話,git的衝突就是核戰爭


Git

看這裡

你所有的疑問都在文檔里

所以

以後來知乎提問前

先去看看文檔

我已經看了5遍了

大多數知乎的技術性問題

都可以在文檔中找到解決方案(主觀性的除外)

因此

先去看文檔吧


推薦閱讀:

md文件怎麼用?
git能不能做到在代碼庫里添加文件,當你沒有的時候才獲取它,有的時候就忽略它?
git如何push時不輸入密碼?
GitCafe 被 Coding 收購的原因和意義?
和一群不用Git的同事寫代碼是一種什麼體驗?

TAG:Git |