• <nav id="wkkge"><strong id="wkkge"></strong></nav>
  • <menu id="wkkge"></menu>
  • Git教程
    Git標簽管理
    Git分支
    Git操作
    Git應用
    GitHub應用
    IDEA對于Git&GitHub的支持
    Git與GitHub使用注意事項

    Git分支策略

     

     

    本文將展示我一年前在自己的項目中成功運用的開發模型。我一直打算把這些東西寫出來,但總是沒有抽出時間,現在終于寫好了。這里介紹的不是任何項目的細節,而是有關分支的策略以及對發布的管理。

     

     

    在我的演示中,所有的操作都是通過 git 完成的。

     

     

    為什么選擇 git ?

     

    為了了斷 git 和中心源代碼控制系統的比較和爭論,請移步這里看看

     

    鏈接1:http://whygitisbetterthanx.com/

     

    鏈接2:https://git.wiki.kernel.org/index.php/GitSvnComparsion

     

    作為一個開發者,我喜歡 git 超過其它任何現有的工具。Git 真正改變了開發者對于合并和分支的認識。在傳統的 CVS/SVN 里,合并/分支總是有點令人害怕的(“注意合并沖突,它們會搞死你的”)。

     

    但是 git 中的這些操作是如此的簡單有效,它們真正作為你每天工作流程的一部分。比如,在 CVS/SVN 的書籍里,分支和合并總是最后一個章節的討論重點(對于高級用戶),而在每一本 git 的書里

     

    鏈接1:https://book.git-scm.com

     

    鏈接2:https://pragprog.com/titles/tsgit/

     

    鏈接3:https://github.com/progit/progit

     

    這些內容已經被包含在第三章(基礎)里了。

     

    因為它的簡單直接和重復性,分支和合并不再令人害怕。版本控制工具比其它任何東西都支持分支/合并。

     

    有關工具就介紹到這里,我們現在進入開發模型這個正題。我要展現的模型本質上無外乎是一個流程的集合,每個團隊成員都有必要遵守這些流程,來達到管理軟件開發流程的目的。

     

     

    分散但也集中

     

    我們的分支模型中使用良好的代碼庫的設置方式,是圍繞一個真實的中心代碼庫的。注意,這里的代碼庫僅僅被看做是一個中心代碼庫(因為 git 是 DVCS,即分散版本控制系統,從技術層面看,是沒有所謂的中心代碼庫的)。我們習慣于把這個中心代碼庫命名為 origin,這同時也是所有 git 用戶的習慣。

     

     

    每一位開發者都向 origin 這個中心結點 pull 和 push。但是除此之外,每一位開發者也可以向其它結點 pull 改變形成子團隊。比如,對于兩個以上開發者同時開發一項大的新特性來說,為了不必過早向 origin 推送開發進度,這就非常有用。在上面的這個例子中,Alice 和 Bob、Alice 和 David、Clair 和 David 都是這樣的子團隊。

     

    從技術角度,這無非意味著 Alice 定義一個名為 Bob 的 git remote,指向 Bob 的代碼庫,反之亦然。

     

     

    主分支

     

     

     

    該開發模型的核心基本和現有的模型是一樣的。中心代碼庫永遠維持著兩個主要的分支:

     

    ? master

     

    ? develop

     

    在 origin 上的 master 分支和每個 git 用戶的保持一致。而和 master 分支并行的另一個分支叫做 develop。

     

    我們認為 origin/master 是其 HEAD 源代碼總是代表了生產環境準備就緒的狀態的主分支。

     

    我們認為 origin/develop 是其 HEAD 源代碼總是代表了最后一次交付的可以趕上下一次發布的狀態的主分支。有人也把它叫做“集成分支”。該源代碼還被作為了 nightly build 自動化任務的來源。

     

    每當 develop 分支到達一個穩定的階段,可以對外發布時,所有的改變都會被合并到master 分支,并打一個發布版本的 tag。具體操作方法我們稍后討論。

     

    因此,每次改動被合并到 master 的時候,這就是一個真正的新的發布產品。我們建議對此進行嚴格的控制,因此理論上我們可以為每次 master 分支的提交都掛一個鉤子腳本,向生產環境自動化構建并發布我們的軟件。

     

     

    支持型分支

     

    我們的開發模型里,緊接著 master 和 develop 主分支的,是多種多樣的支持型分支。它們的目的是幫助團隊成員并行處理每次追蹤特性、準備發布、快速修復線上問題等開發任務。和之前的主分支不同,這些分支的生命周期都是有限的,它們最終都會被刪除掉。

     

    我們可能會用到的不同類型的分支有:

     

    ? feature 分支

     

    ? release 分支

     

    ? hotfix 分支

     

    每一種分支都有一個特別的目的,并且有嚴格的規則,諸如哪些分支是它們的起始分支、哪些分支必須是它們合并的目標等。我們快速把它們過一遍。

     

    這些“特殊”的分支在技術上是沒有任何特殊的。分支的類型取決于我們如何運用它們。它們完完全全都是普通而又平凡的 git 分支。

     

     

    ? 可能派發自:develop

     

    ? 必須合并回:develop

     

    ? 分支命名規范:除了 master、develop、release-* 或 hotfix-* 的任何名字

     

    Feature 分支(有時也被稱作 topic 分支)用來開發包括即將發布或遠期發布的新的特性。當我們開始開發一個特性的時候,發布合并的目標可能還不太確定。Feature 分支的生命周期會和新特性的開發周期保持同步,但是最終會合并回 develop (恩,下次發布的時候把這個新特性帶上)或被拋棄(真是一次杯具的嘗試啊)。

     

    Feature 分支通常僅存在于開發者的代碼庫中,并不出現在 origin 里。

     

     

    創建一個 feature 分支

     

    當開始一個新特性的時候,從 develop 分支派發出一個分支

     

    $ git checkout -b myfeature develop
    Switched to a new branch "myfeature"

     

    把完成的特性合并回 develop

     

    完成的特性可以合并回 develop 分支并趕上下一次發布:

     

    $ git checkout develop
    Switched to a new branch "develop"
    $ git merge --no-ff myfeature
    Updating ea1b82a..05e9557
    (Summary of changes)
    $ git branch -d myfeature
    Deleted branch myfeature (was 05e9557)
    $ git push origin develop

     

    -no-ff 標記使得合并操作總是產生一次新的提交,哪怕合并操作可以快速完成。這個標記避免將 feature 分支和團隊協作的所有提交的歷史信息混在主分支的其它提交之后。比較一下:

     

     

    在右邊的例子里,我們不可能從 git 的歷史記錄中看出來哪些提交實現了這一特性——你可能不得不查看每一筆提交日志。恢復一個完整的特性(比如通過一組提交)在右邊變成了一個頭疼事情,而如果使用了 --no-ff 之后,就變得簡單了。

     

    是的,這會創造一些沒有必要的(空的)提交記錄,但是得到的是大量的好處。

     

    不幸的是,我還沒有找到一個在 git merge 時默認就把 --no-ff 標記打上的辦法,但這很重要。

     

     

    release 分支

     

    ? 可能派發自:develop

     

    ? 必須合并回:develop 和 master

     

    ? 分支命名規范:release-*

     

    Release 分支用來支持新的生產環境發布的準備工作。允許在最后階段產生提交點(dotting i's)和交匯點(crossing t's)。而且允許小幅度的問題修復以及準備發布時的meta數據(比如版本號、發布日期等)。在 release 分支做了上述這些工作之后,develop 分支會被“翻篇兒”,開始接收下一次發布的新特性。

     

    我們選擇(幾近)完成所有預期的開發的時候,作為從 develop 派發出 release 分支的時機。最起碼所有準備構建發布的功能都已經及時合并到了 develop 分支。而往后才會發布的功能則不應該合并到 develop 分支——他們必須等到 release 分支派發出去之后再做合并。

     

    在一個 release 分支的開始,我們就賦予其一個明確的版本號。直到該分支創建之前,develop 分支上的描述都是“下一次”release 的改動,但這個“下一次”release 其實也沒說清楚是 0.3 release 還是 1.0 release。而在一個 release 分支的開始時這一點就會確定。這將成為有關項目版本號晉升的一個守則。

     

     

    創建一個 release 分支

     

    Release 分支派發自 develop 分支。比如,我們當前的生產環境發布的版本是 1.1.5,馬上有一個 release 要發布了。develop 分支已經為“下一次”release 做好了準備,并且我們已經決定把新的版本號定為 1.2 (而不是 1.1.6 或 2.0)。所以我們派發一個 release 分支并以新的版本號為其命名:

     

    $ git checkout -b release-1.2 develop
    Switched to a new branch "release-1.2"
    $ ./bump-version.sh 1.2
    Files modified successfully, version bumped to 1.2.
    $ git commit -a -m "Bumped version number to 1.2"
    [release-1.2 74d9424] Bumped version number to 1.2
    1 files changed, 1 insertions(+), 1 deletions(-)

     

    創建好并切換到新的分支之后,我們完成對版本號的晉升。這里的 bump-version.sh是一個虛構的用來改變代碼庫中某些文件以反映新版本的 shell 腳本。(當然你也可以手動完成這些改變——重點是有些文件發生了改變)然后,晉升了的版本號會被提交。

     

    這個新的分支會存在一段時間,直到它確實發布出去了為止。期間可能會有 bug 修復(這比在 develop 做更合理)。但我們嚴格禁止在此開發龐大的新特性,它們應該合并到 develop 分支,并放入下次發布。

     

     

    完成一個 release 分支

     

    當 release 分支真正發布成功之后,還有些事情需要收尾。首先,release 分支會被合并到 master (別忘了,master 上的每一次提交都代表一個真正的新的發布);然后,為master 上的這次提交打一個 tag,以便作為版本歷史的重要參考;最后,還要把 release 分支產生的改動合并回 develop,以便后續的發布同樣包含對這些 bug 的修復。

     

    前兩部在 git 下是這樣操作的:

     

    $ git checkout master
    Switched to branch 'master'
    $ git merge --no-ff release-1.2
    Merge made by recursive
    (Summary of changes)
    $ git tag -a 1.2

     

    現在發布工作已經完成了,同時 tag 也打好了,用在未來做參考。

     

    補充:你也可以通過 -s 或 -u  <key>標記打 tag。

     

    為了保留 release 分支里的改動記錄,我們需要把這些改動合并回 develop。git 操作如下:

     

    $ git checkout develop
    Switched to branch 'develop'
    $ git merge --no-ff release-1.2
    Merge made by recursive.
    (Summary of changes)

     

    這一步有可能導致沖突的發生(只是有理論上的可能性,因為我們已經改變了版本號),一旦發現,解決沖突然后提交就好了。

     

    現在我們真正完成了一個 release 分支,該把它刪掉了,因為它的使命已經完成了:

     

    $ git branch -d release-1.2
    Deleted branch release-1.2 (was ff452fe).

     

     

    hotfix分支

     

     

     

    ? 可能派發自:master

     

    ? 必須合并回:develop 和 master

     

    ? 分支命名規范:hotfix-*

     

    Hotfix 分支和 release 分支非常類似,因為他們都意味著會產生一個新的生產環境的發布,盡管 hotfix 分支不是先前就計劃好的。他們在實時的生產環境版本出現意外需要快速響應時,從 master 分支相應的 tag 被派發。

     

    我們這樣做的根本原因,是為了讓團隊其中一個人來快速修復生產環境的問題,其他成員可以按工作計劃繼續工作下去而不受太大影響。

     

     

    創建一個 hotfix 分支

     

    Hotfix 分支創建自 master 分支。例如,假設 1.2 版本是目前的生產環境且出現了一個嚴重的 bug,但是目前的 develop 并不足夠穩定。那么我們可以派發出一個 hotfix 分支來開始我們的修復工作:

     

    $ git checkout -b hotfix-1.2.1 master
    Switched to a new branch "hotfix-1.2.1"
    $ ./bump-version.sh 1.2.1
    Files modified successfully, version bumped to 1.2.1.
    $ git commit -a -m "Bumped version number to 1.2.1"
    [hotfix-1.2.1 41e61bb] Bumped version number to 1.2.1
    1 files changed, 1 insertions(+), 1 deletions(-)

     

    別忘了在派發出分支之后晉升版本號!

     

    然后,修復 bug,提交改動。通過一個或多個提交都可以。

     

    $ git commit -m "Fixed severe production problem"
    [hotfix-1.2.1 abbe5d6] Fixed severe production problem
    5 files changed, 32 insertions(+), 17 deletions(-)

     

     

    完成一個 hotfix 分支

     

    當我們完成之后,對 bug 的修復需要合并回 master,同時也需要合并回 develop,以保證接下來的發布也都已經解決了這個 bug。這和 release 分支的完成方式是完全一樣的。

     

    首先,更新 master 并為本次發布打一個 tag:

     

    $ git checkout master
    Switched to branch 'master'
    $ git merge --no-ff hotfix-1.2.1
    Merge made by recursive
    (Summary of changes)
    $ git tag -a 1.2.1

     

    補充:你也可以通過 -s 或 -u 標記打 tag。

     

    然后,把已修復的 bug 合并到 develop:

     

    $ git checkout develop
    Switched to branch 'develop'
    $ git merge --no-ff hotfix-1.2.1
    Merge made by recursive
    (Summary of changes)

     

    這個規矩的一個額外之處是:如果此時已經存在了一個 release 分支,那么 hotfix 的改變需要合并到這個 release 分支,而不是 develop 分支。因為把對 bug 的修復合并回 release 分支之后,release 分支最終還是會合并回 develop 分支的。(如果在 develop 分支中立刻需要對這個 bug 的修復,且等不及 release 分支合并回來,則你還是可以直接合并回 develop 分支的,這是絕對沒問題的)

     

    最后,刪掉這個臨時的分支:

     

    $ git branch -d hotfix-1.2.1
    Deleted branch hotfix-1.2.1 (was abbe5d6).

     

    全部教程
  • <nav id="wkkge"><strong id="wkkge"></strong></nav>
  • <menu id="wkkge"></menu>
  • 面对面棋牌游戏