走進git時代, 你該怎么玩?

oar67h82 8年前發布 | 25K 次閱讀 Git 版本控制系統

來自: http://yq.aliyun.com/articles/5843

首先,這篇分享不是git命令操作大全,不是某代碼托管服務的硬廣, 只是希望激發仍然在使用中世紀時期版本管理系統的同學們,能夠放棄你手里的SVN,轉向更先進的思路。

所以,大家不會看到非常多的Command Line 教你Step By Step Git init :) , 請放心像讀故事一樣,慢慢理解為什么要擁抱Git,以及玩轉Git你需要做什么?

本文大概分為以下幾個篇章:

  1. 版本管理的發展歷史

    </li>

  2. 為什么Git能如此的火爆

    </li>

  3. 不要用SVN去思考Git

    </li>

  4. 玩轉Git與協作

    </li>

  5. 學習Git的一些參考資料

    </li> </ol>

    版本管理的發展歷史

    • 什么是版本管理, 當你在兒童時期玩游戲的時候,在打Boss之前的存檔, 就是最原始版本管理的目的。

      </li>

    • 那么我們先來看看版本管理的歷史, 我想引用coolshell.cn里的一些內容,先來看從網上找到的一張版本管理時代變遷圖 :

      </li> </ul>

      • 這張圖上分成了四個時期:

        </li>

      • 史前時期:1982年的RCS。現在你可能還能在Unix的發布包中找到它。

        </li>

      • 古典時期:1990年的CVS,1985年的PVCS,1992年的clearcase(價格貴,功能復雜,當然,今天還有人在用),微軟的VSS(Welcome to Hell),90年代中期的Perforce(P4,這個工具今天都還在被廣泛地使用,尤其是那些中等大小卻有著大量開發團隊的公司,現在是Google內部最大的代碼管理器)。

        </li>

      • 中世紀時期:SVN,AccuRev(強力支持branch和merge,其扮演了一個很重要角色幫助社區脫離clearcase和CVS),

        </li>

      • 文藝復興時期:BitKeeper——Sun的內部管理工具,Linux的內核代碼2002年也用這個工具,其實,很多開源工程都在用這個工具,2005年這個工具的東家BitMover對大家對BitKeeper逆向工程很不滿,于是停止支持開源,于是出現了Git。

        </li>

      • Git 誕生于一個極富紛爭大舉創新的年代。 可以看到同期出現了其他不少創新的版本管理系統:

        </li>

      • Mercurial (Hg) 第一次出現在2005年4月,也是因為BitKeeper不免費了。Hg可以和Git在一起使用,見: HG_GIT 。但是Hg和Git在設計上不一樣,他們對提交/變更的概念是一樣的,只不過Git用tree來實現,而Hg則是用扁平的文件和目錄來實現(revlog)

        </li>

      • Darcs (Darcs Advanced Revision Control System)是另一個讓你擺脫Subversion和CVS的工具,2002年開始,今年是2.5版。它的優勢是性能,以及他與眾不同的歷史版本管理——管理patches而不是snapshot(提交/修改),當然,這樣一來,歷史改變看上去很不好懂。

        </li>

      • Bazaar (bzr) 是另一個開源的 DVCS,它試圖給SCM的世界里帶來一些新的東西。其由Canonical開發(Ubuntu的那個公司),在2008年成為GNU。

        </li>

      • Plastic在2006年出現,強力地支持branch和merge,其還提供了強大的圖示,包括3D的版本樹,Plastic主要是為了讓中等開發團隊使用,介于大型的團隊(ClearCase)和小型的團隊(Subversion)之間。

        </li>

      • Team Foundation Server (TFS),微軟的新一代SCM工具,主要是為了VSS的失敗負責,但是他還不是版本管理上還是很強,只不過,他集成了一大堆各種各樣的工具,比如:issue tracking,test management等。

        </li> </ul>

        為什么Git能如此的火爆

        • 我認為:首先,Git 很牛逼, 然后,基于Git的產品很牛逼 。

          </li>

        • Git 產生的背景相信大家或多或少都聽過,Linux 內核開源項目在全世界有無數人在參與,因為人太多了,所以他們在1991~2002年間絕大多數的維護工作都花在了提交補丁和保存歸檔的繁瑣事務上。 到 2002 年,整個項目組開始啟用一個專有的分布式版本控制系統 BitKeeper 來管理和維護代碼。

          </li>

        • 到了 2005 年,開發 BitKeeper 的公司和 Linux 內核開源社區解除了合作關系,不免費給他們用了。 基于和BitKeeper的殘酷經驗, 逼迫他們必須自己開發一個版本管理系統, 于是按照下面幾個要求開始:

          • 速度
          • 簡單的設計
          • 對非線性開發模式的強力支持(允許成千上萬個并行開發的分支)
          • 完全分布式
          • 有能力高效管理類似 Linux 內核一樣的超大規模項目(速度和數據量)
          • </ul> </li>

          • Git的第一個版本是Linux之父Linus Torvalds親手操刀設計和實現的(據說只用了一個周末),Linus不僅僅給出一個原始設計(簡單的、干凈的、天才的),同時,他也用自己那獨一無二的風格催生了這個項目(請參看: http://codicesoftware.blogspot.com/2007/05/linus-torvalds-on-git-and-scm.html 還是被墻)。

            </li>

          • 在Linus介紹Git的著名的演講中,他強烈地批評(應該算是侮辱)了CVS,SVN,和Perforce:“Subversion是史上最毫無意義的項目,從項目開始就是這樣了”,“如果你喜歡CVS,那么你現在應該在某個精神病研究中心或是別的地方”,“別在用Preforce了,它是十分糟糕和可悲的,這絕對絕對是真的”。無論是反對還是喜歡,Linus的確是改變了歷史——中世紀已經過去了,現在的世界由分布式系統主宰,以及消除branch和merge的恐懼。

            </li>

          • Git 基于 DAG 結構 (Directed Acyclic Graph),其運行起來相當的快。在Git發布后的來年,世界上所有的大型的開源項目全部從Subversion遷移到了Git上。

            </li>

          • 為什么說基于Git的產品很牛逼, 因為Github真是很大,從Linux內核遷移到Github 上開始,經歷了七八年到現在,已經成為全世界公認的開源代碼,開源社區的地方。 無數程序員們都是先知道Github, 才知道Git。所以,學習Git, 網絡上無數的命令大全,上手指南,高階學習的帖子無處不在。

            </li>

          • 所以,Git可能并不是最簡單的,但它已經是現在的主流.

            </li> </ul>

            不要用SVN去思考Git

            • 說完上面那么多的歷史,我不想再費力氣說明為什么Git 優與SVN了, 什么因為是C寫的所以運行更快我,因為是分布式的比中心化得更方便, 元數據方式存儲比文件存儲更優等等, 因為SVN,已經是上一個時代的產物了。

              </li>

            • 那么, 這個章節想要說明的是,不要用SVN的思想和操作方式 去理解Git 。

              </li>

            • 首先, Git 到底是什么? 很多人說,git是分布式,git本質是一個 key/value 的文件管理系統,git是對blob二進制數據, tree最好的解釋。

              </li>

            • 我個人最認可對git的理解是: git is a directory content, management system, tree history, storage system , stupid content tracker and a toolkit

              </li>

            • Git 和 SVN 思想最大的差別有四個:

              </li> </ul>

              1. 去中心卻集中

                </li>

              2. 直接記錄快照,而非差異

                </li>

              3. 不一樣的分支概念

                </li>

              4. 三個工作區,三個文件狀態

                </li> </ol>

                去中心卻集中(Decentralized but centralized)

                • 我們都知道Git是一個DVCS(分布式版本管理系統),在技術層面上并不存在一個像中心倉庫這樣的東西 , 所有的數據都在本地,不存在誰是中心,大家每個人本地都一樣, 但我們仍然需要協作,Git 同樣有Server的概念, 在下圖中,origin 是我們熟知的名詞,這個中心是誰,就取決于你用什么代碼托管系統了。 你可以在公司本地服務器搭建Git Server, 當然我更推薦使用阿里的產品code.aliyun.com
                • </ul>

                  • 每個開發者拉取(pull)并推送(push)到origin。但除了這種集中式的推送拉取關系,每個開發者也可能會從其他的開發者處拉取代碼的變更,從而形成一個子團隊。例如,當與兩個或更多的開發者協同工作于一個大的新特性時,在將工作代碼推送到持久的origin之前,這可能很有用。在上圖中,Alice和Bob,Alice和David,以及Clair和David,分別構成了子團隊。

                    </li>

                  • 從技術上講,這只不過意味著Alice定義了一個名為bob的Git的remote,它指向了Bob的軟件倉庫。反之亦然。

                    </li> </ul>

                    直接記錄快照,而非差異

                    • Git 第二個思想也是和SVN最大的差異化,即每一個版本都是直接記錄快照,而非文件的差異。 下面兩個對比圖在網上是廣為流傳大家應該熟悉:

                      </li>

                    • SVN :

                      </li> </ul>

                      • Git:
                      • </ul>

                        !

                        • GIT 使用SHA-1算法計算數據的校驗和 ,通過文件的內容或目錄計算出SHA-1哈希值,作為指紋字符串, 每個Version 都是一個快照。 所以Git的最小概念是倉庫,SVN的最小概念是文件。
                        • </ul>

                          不一樣的分支概念

                          • 因為不是記錄文件差異,Git的分支本質是一個指向提交快照的指針,是從某個提交快照往回看的歷史。

                            </li>

                          • 當創建/切換分支的時候,只是變換了指針指向而已,所以會發現創建分支非常的快,同樣當git init 之后就會有一個默認的分支, 我們通常叫master ,但這實際上不是主干,沒有所謂的主干和分支的差別, master只是命名為master的一個分支, 是我們為了版本管理的習慣叫法而已。 ,

                            </li>

                          • SVN創建一個分支, 是的的確確的復制了一份文件, 而如剛才說SVN的每一次Version 是記錄了文件差異, 因此假入你commit了一個1M的文件到SVN服務器, SVN Server的存儲增加了1M,當你刪除了這個1M大小的文件并Commit的時候,SVN Server的存儲又增加了1M。 所以,你是不會想知道像BAT這三家公司內部的SVN Server今天占用了多大存儲空間的-。-

                            </li> </ul>

                            三個工作區,三個文件狀態

                            • 在 Git 中,存在三個工作區域:

                              • 工作目錄
                              • 暫存區域
                              • 本地倉庫
                              • </ul> </li>

                              • 同時,文件有三種狀態:

                                • 已提交(committed):該文件被安全地保存在了本地數據庫
                                • 已修改(modified):修改了某個文件,但還沒有保存
                                • 已暫存(staged):把已修改的文件放下下次保存的清單中
                                • </ul> </li>

                                • 下圖說明了這三個區域和文件狀態的差別:

                                  </li> </ul>

                                  • 所以,在Git中,你可以暫存部分文件,甚至一個文件中的部分內容,你的本地可以將版本管理玩的非常復雜和有趣。 這也是為什么 SVN 用戶最常疑問 Git 為什么每次都要TM的 git add 才能再 commit 的原因
                                  • </ul>

                                    玩轉Git 與協作

                                    • Git 常用的命令這里不解釋了, 但是我們都是在公司內的程序員,即便是個人開發者也會有在社區的伙伴們,所以代碼管理一定要有協作的部分, 你一定不是一個人在戰斗。

                                      </li>

                                    • 因此我個人的理解,什么是一個好的代碼庫管理: 庫不大, 分支少,tag多, 分支或CI log 和Issue關聯,分支開發master發布, 小步迭代, 版本樹清晰漂亮,功能分支永遠和Master離的很近, 所有開發熟悉rebase和遵循Merge request習慣

                                      </li>

                                    • 話有點糙,實際上就是敏捷開發中的一部分概念, 即便一定要拉出功能分支,也一定要快速合并,否則不如變成兩個代碼庫,兩個應用。

                                      </li>

                                    • 所以玩轉git協作, merge , rebase 和 cherry-pick 是你一定要理解的三個概念。

                                      </li>

                                    • 首先, Merge , 合并代碼,人人都能理解, 在Git中存在 fast forward 和no fast fast forward branch merging , 并沒有好壞之分, 差別在于,fast forward 實際上不會產生代碼合并, 比如你改了a文件,我改了b文件,這兩個分支Commit的文件不存在任何的合并, 所以可以進行ff merge,從而使版本樹是一條線; 而產生了merge 之后的版本樹會有多一個merge節點產生, 版本樹是兩條線合并到一條線。

                                      </li>

                                    • Rebase 和 Cherry-pick 這里要多講兩句了 ~

                                      </li> </ul>

                                      cherry-pick

                                      • cherry-pick的對象可以是分支也可以是一個commit.
                                      • </ul>

                                        A-B-C-D
                                             \
                                              E-F-G

                                        • 當我執行 git cherry-pick <commit id of F> , 就會把分支上的 F 拿過來,變成下面的效果:
                                        • </ul>

                                          A-B-C-D-F‘
                                               \
                                                E-F-G

                                          • cherry-pick可以自動生成commit,這時候本分支上會有一個新的commit id,但是提交內容 F’=F。你再本分支上看到的log將是賞心悅目的直線。

                                            </li>

                                          • 如果cherry-pick的是一個分支呢?同樣的例子, git cherry-pick <branch name> 會將另一分支上的每個提交按順序加到本地,如果有沖突會提醒,解決沖突后提交即可。

                                            </li> </ul>

                                            A-B-C-D             A-B-C-D-E-F-G
                                                 \        ==>        \
                                                  E-F-G               E-F-G

                                            rebase

                                            • 從字面上理解是復位基底,也是很形象的。它大概的意思如下:
                                            • </ul>

                                              A-B-C-D-H             A-B-C-D-H
                                                   \        ==>            \
                                                    E-F-G                   E-F-G

                                              • 詳細的解釋和用法推薦看: http://gitbook.liuhui998.com/4_2.html
                                              • </ul>

                                                因此:

                                                • cherry-pick 和 rebase 的區別是,一個是把別人的拿來,別人的提交會在HEAD上加入。rebase是把自己的根本切換,別人的提交會在自己的尾部。

                                                  </li>

                                                • cherry-pick 和 rebase 的好處是log簡潔,是一條直線。適用于自己本地的分支管理,讓自己的提交盡量是一條直線。

                                                  </li>

                                                • merge 會產生一次提交,適用場景是多人合作的場景,不同或者同一分支開發時。會產生有交點的多條線, 除非是ff的merge。

                                                  </li> </ul>

                                                  學習Git的一些參考資料

                                                  • 推薦一堆沒用, 其實學習Git, 就兩本書足以成為使用上面的專家。 Pro Git 簡體中文版 ,這個上手可以。 還有一本 《Git權威指南

                                                    》 這個可以作為工具書了,因為里面講的比較深,講到了Git 一些底層命令(類似 git rev-parse , git ls-tree 這種), 如果你是SCM 或者公司內的版本管理者,是需要有這本書的。

                                                    </div> </li>

                                                  • 另外如果你是linux 或者 mac 用戶, 命令行將是Git 最好的伙伴。 如果是Windows ,也建議直接用 Git bash 來進行操作。

                                                    </li>

                                                  • 不過,如果為了使用更加的方便, 建議裝 SourceTree 或者 Github 客戶端 這兩個客戶端工具。 不要裝小烏龜或者別的工具了, 太難用。

                                                    </li> </ul>

                                                    寫在最后

                                                    • 當然 , Git 和SVN的思想差異, Git 中需要學習的地方很多, 上面提到的都只是我個人認為比較重要的點而已。 希望這篇文章能讓大家從SVN等其他版本管理工具中遷移到Git上來。

                                                      </li>

                                                    • 之后針對代碼管理, 我們還會推出 《如何從SVN遷移到GIT》 ,會包含如何從一個svn repo Step By Step 遷移到Git repo 的命令教程。

                                                      </li>

                                                    • 以及 《玩轉云Code最佳實踐》 ,會講在 https://code.aliyun.com 上進行代碼協作的最佳實踐 。

                                                      </li>

                                                    • 以及 《云上持續交付最佳實踐》 , 會包含如何使用 https://crp.aliyun.com 及阿里云Docker 容器服務 如何進行持續集成,到持續交付的實踐教程, 敬請期待。

                                                      </li> </ul> </div> </code></code></code></code>

 本文由用戶 oar67h82 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!