1. 程式人生 > >使用git和github進行協同開發流程

使用git和github進行協同開發流程

搜到的一位大神寫的東西,感覺很不錯。收了!

它的老家:https://github.com/livoras/blog/issues/7


以下是原文內容:


目錄

  • 前言
  • 倉庫(Repository)
    • 源倉庫
    • 開發者倉庫
  • 分支(Branch)
    • 永久性分支
    • 暫時性分支
  • 工作流(workflow)
  • 總結
  • 參考資料

前言

(本文假設各位已經對基本git的基本概念、操作有一定的理解,如無相關git知識,可以參考Pro Git這本書進行相關的學習和練習)

很多專案開發都會採用git這一優秀的分散式版本管理工具進行專案版本管理,使用github開源平臺作為程式碼倉庫託管平臺。由於git的使用非常靈活,在實踐當中衍生了很多種不同的工作流程,不同的專案、不同的團隊會有不同的協作方式。

本文將介紹一種前人已經在各種大小專案中經過千錘百煉總結出來的一種比較成功的git工作流,這種工作流已經被成功用於許多團隊開發當中。掌握git,掌握這種工作流,對大家以後的學習、開發工作大有好處。

先上一張圖嚇大家一下:

workflow

上面一張圖展示了一種使用git進行專案協同開發的模式,接下來會進行詳細介紹。

倉庫(Repository)

在專案的開始到結束,我們會有兩種倉庫。一種是源倉庫(origin),一種是開發者倉庫。上圖中的每個矩形都表示一個倉庫,正中間的是我們的源倉庫,而其他圍繞著源倉庫的則是開發者倉庫。

源倉庫

在專案的開始,專案的發起者構建起一個專案的最原始的倉庫,我們把它稱為origin

,例如我們的PingHackers網站,origin就是這個PingHackers/blog了。源倉庫的有兩個作用:

  1. 彙總參與該專案的各個開發者的程式碼
  2. 存放趨於穩定和可釋出的程式碼

源倉庫應該是受保護的,開發者不應該直接對其進行開發工作。只有專案管理者(通常是專案發起人)能對其進行較高許可權的操作。

開發者倉庫

上面說過,任何開發者都不會對源倉庫進行直接的操作,源倉庫建立以後,每個開發者需要做的事情就是把源倉庫的“複製”一份,作為自己日常開發的倉庫。這個複製,也就是github上面的fork

每個開發者所fork的倉庫是完全獨立的,互不干擾,甚至與源倉庫都無關。每個開發者倉庫相當於一個源倉庫實體的影像,開發者在這個影像中進行編碼,提交到自己的倉庫中,這樣就可以輕易地實現團隊成員之間的並行開發工作。而開發工作完成以後,開發者可以向源倉庫傳送pull request

,請求管理員把自己的程式碼合併到源倉庫中,這樣就實現了分散式開發工作,和最後的集中式的管理。

分支(Branch)

分支是git中非常重要的一個概念,也是git這一個工具中的大殺器,必殺技。在其他集中式版本管理工具(SVN/CVS)把分支定位為高階技巧,而在git中,分支操作則是每個開發人員日常工作流。利用git的分支,可以非常方便地進行開發和測試,如果使用git沒有讓你感到輕鬆和愉悅,那是因為你還沒有學會使用分支。不把分支用出一點翔來,不要輕易跟別人說你用過git。

在文章開頭的那張圖中,每一個矩形內部紛繁的枝蔓便是git的分支模型。可以看出,每個開發者的倉庫都有自己的分支路線,而這些分支路線會通過程式碼彙總對映到源倉庫中去。

我們為git定下一種分支模型,在這種模型中,分支有兩類,五種

  • 永久性分支
    • master branch:主分支
    • develop branch:開發分支
  • 臨時性分支
    • feature branch:功能分支
    • release branch:預釋出分支
    • hotfix branch:bug修復分支

永久性分支

永久性分支是壽命無限的分支,存在於整個專案的開始、開發、迭代、終止過程中。永久性分支只有兩個masterdevelop

master:主分支從專案一開始便存在,它用於存放經過測試,已經完全穩定程式碼;在專案開發以後的任何時刻當中,master存放的程式碼應該是可作為產品供使用者使用的程式碼。所以,應該隨時保持master倉庫程式碼的清潔和穩定,確保入庫之前是通過完全測試和程式碼reivew的。master分支是所有分支中最不活躍的,大概每個月或每兩個月更新一次,每一次master更新的時候都應該用git打上tag,說明你的產品有新版本釋出了。

develop:開發分支,一開始從master分支中分離出來,用於開發者存放基本穩定程式碼。之前說過,每個開發者的倉庫相當於源倉庫的一個映象,每個開發者自己的倉庫上也有masterdevelop。開發者把功能做好以後,是存放到自己的develop中,當測試完以後,可以向管理者發起一個pull request,請求把自己倉庫的develop分支合併到源倉庫的develop中。

所有開發者開發好的功能會在源倉庫的develop分支中進行彙總,當develop中的程式碼經過不斷的測試,已經逐漸趨於穩定了,接近產品目標了。這時候,我們就可以把develop分支合併到master分支中,釋出一個新版本。所以,一個產品不斷完善和釋出過程就正如下圖:

master & develop

注意,任何人不應該向master直接進行無意義的合併、提交操作。正常情況下,master只應該接受develop的合併,也就是說,master所有程式碼更新應該源於合併develop的程式碼。

暫時性分支

暫時性分支和永久性分支不同,暫時性分支在開發過程中是一定會被刪除的。所有暫時性分支,一般源於develop,最終也一定會迴歸合併到develop

feature:功能性分支,是用於開發專案的功能的分支,是開發者主要戰鬥陣地。開發者在本地倉庫從develop分支分出功能分支,在該分支上進行功能的開發,開發完成以後再合併到develop分支上,這時候功能性分支已經完成任務,可以刪除。功能性分支的命名一般為feature-*,*為需要開發的功能的名稱。

feature branch

舉一個例子,假設我是一名PingHackers網站的開發者,已經把源倉庫fork了,並且clone到了本地。現在要開發PingHackers網站的“討論”功能。我在本地倉庫中可以這樣做:

step 1: 切換到develop分支

    >>> git checkout develop

step 2: 分出一個功能性分支

    >>> git checkout -b feature-discuss

step 3: 在功能性分支上進行開發工作,多次commit,測試以後...

step 4: 把做好的功能合併到develop

    >>> git checkout develop

    # 回到develop分支

    >>> git merge --no-ff feature-discuss
    # 把做好的功能合併到develop中

    >>> git branch -d feature-discuss
    # 刪除功能性分支

    >>> git push origin develop
    # 把develop提交到自己的遠端倉庫中

這樣,就完成一次功能的開發和提交。

release:預釋出分支,當產品即將釋出的時候,要進行最後的調整和測試,這時候就可以分出一個預釋出分支,進行最後的bug fix。測試完全以後,釋出新版本,就可以把預釋出分支刪除。預釋出分支一般命名為release-*

hotfix:修復bug分支,當產品已經發布了,突然出現了重大的bug。這時候就要新建一個hotfix分支,繼續緊急的bug修復工作,當bug修復完以後,把該分支合併到masterdevelop以後,就可以把該分支刪除。修復bug分支命名一般為hotfix-*

releasehotfix分支離我們還比較遙遠。。就不詳述,有興趣的同學可以參考本文最後的參考資料進行學習。

工作流(Workflow)

囉嗦講了這麼多,概念永遠是抽象的。對於新手來說,都喜歡一步一步的步驟傻瓜教程,接下來,我們就一步一步來操作上面所說的工作流程,大家感受一下:

Step 1:源倉庫的構建

這一步通常由專案發起人來操作,我們這裡把管理員設為PingHackers,假設PingHackers已經為我們建立起了一個源倉庫PingHackers/git-demo,並且已經初始化了兩個永久性分支masterdevelop,如圖:



Step 2:開發者fork源倉庫

源倉庫建立以後,每個開發就可以去複製一份源倉庫到自己的github賬號中,然後作為自己開發所用的倉庫。假設我是一個專案中的開發者,我就到PingHackers/git-demo專案主頁上去fork

fork

fork完以後,我就可以在我自己的倉庫列表中看到一個和源倉庫一模一樣的複製品。這時就應該感嘆,你以後要和它相依為命了:

fork-origin

Step 3:把自己開發者倉庫clone到本地

這一步應該不用教,git clone

Step 4:構建功能分支進行開發

進入倉庫中,按照前面說所的構建功能分支的步驟,構建功能分支進行開發、合併,假設我現在要開發一個“討論”功能:

    >>> git checkout develop
    # 切換到`develop`分支

    >>> git checkout -b feature-discuss
    # 分出一個功能性分支

    >> touch discuss.js
    # 假裝discuss.js就是我們要開發的功能

    >> git add .
    >> git commit -m 'finish discuss feature'
    # 提交更改

    >>> git checkout develop
    # 回到develop分支

    >>> git merge --no-ff feature-discuss
    # 把做好的功能合併到develop中

    >>> git branch -d feature-discuss
    # 刪除功能性分支

    >>> git push origin develop
    # 把develop提交到自己的遠端倉庫中

這時候,你上自己github的專案主頁中develop分支中看看,已經有discuss.js這個檔案了:

push

Step 5:向管理員提交pull request

假設我完成了“討論”功能(當然,你還可能對自己的develop進行了多次合併,完成了多個功能),經過測試以後,覺得沒問題,就可以請求管理員把自己倉庫的develop分支合併到源倉庫的develop分支中,這就是傳說中的pull request

pull-request

點選上圖的綠色按鈕,開發者就可以就可以靜靜地等待管理員對你的提交的評審了。

pull-finished

Step 6 管理員測試、合併

接下來就是管理員的操作了,作為管理員的PingHackers登陸github,便看到了我對源倉庫發起的pull request

pull-request-origin

這時候PingHackers需要做的事情就是:

  1. 對我的程式碼進行review。github提供非常強大的程式碼review功能:
    reivew
  2. 在他的本地測試新建一個測試分支,測試我的程式碼:
    >> git checkout develop
    # 進入他本地的develop分支

    >> git checkout -b livoras-develop
    # 從develop分支中分出一個叫livoras-develop的測試分支測試我的程式碼

    >> git pull https://github.com/livoras/git-demo.git develop
    # 把我的程式碼pull到測試分支中,進行測試
  1. 判斷是否同意合併到源倉庫的develop,如果經過測試沒問題,可以把我的程式碼合併到源倉庫的develop中:
    >> git checkout develop
    >> git merge --no-ff livoras-develop
    >> git push origin develop

注意,PingHakers一直在操作的倉庫是源倉庫。所以我們經過上面一系列操作以後,就可以在源倉庫主頁中看到:

merge

經過輾轉曲折的路程,我們的discuss.js終於從我的開發倉庫的功能分支到達了源倉庫的develop分支中。以上,就是一個git & github協同工作流的基本步驟。

總結

git這一個工具博大精深,使用如此噁心而又如此靈活和優雅的工具;此又為一神器,大家還是多動手,多查資料,讓git成為自己的一項基本技能,幫助自己處理各種專案團隊協同工作的問題,成為一個高效的開發者、優秀的專案的管理者。送大家一張神圖,好好領悟:

Overview

最後給出一些參考資料,供參考學習。