Git
英文 ▾ 主題 ▾ 最新版本 ▾ gitworkflows 最後更新於 2.35.0

名稱

gitworkflows - Git 建議工作流程概觀

概要

git *

描述

本文檔試圖記錄並闡述 git.git 本身使用的一些工作流程要素。許多想法普遍適用,儘管對於較少人參與的小型專案來說,很少需要完整的工作流程。

我們制定了一套「規則」以供快速參考,而文字則試圖闡述每個規則的動機。不要總是逐字理解它們;您應該重視行動的合理理由,而不是像這篇手冊一樣的條文。

區隔變更

一般而言,您應該嘗試將變更拆分為小的邏輯步驟,並分別提交每個步驟。它們應該是連貫的,獨立於任何後續提交而工作,通過測試套件等等。這使得審閱過程更加容易,並且歷史記錄對於後續檢查和分析(例如使用 git-blame[1]git-bisect[1])更有用。

為了實現這一點,請嘗試從一開始就將您的工作拆分為小步驟。將幾個提交合併在一起總是比將一個大型提交拆分為幾個更容易。不要害怕在過程中做出太小或不完美的步驟。您可以在發布之前隨時使用 git rebase --interactive 返回並編輯提交。您可以使用 git stash push --keep-index 獨立於其他未提交的變更來執行測試套件;請參閱 git-stash[1] 的範例章節。

管理分支

有兩個主要的工具可以用於將一個分支上的變更包含到另一個分支上:git-merge[1]git-cherry-pick[1]

合併有許多優點,因此我們嘗試僅使用合併來解決盡可能多的問題。挑選提交 (cherry-picking) 仍然偶爾有用;請參閱下方的「向上合併」範例。

最重要的是,合併在分支層級運作,而挑選提交在提交層級運作。這意味著合併可以輕鬆地傳遞 1、10 或 1000 個提交的變更,這反過來意味著工作流程可以更好地擴展到大量的貢獻者(和貢獻)。合併也更容易理解,因為合併提交是一個「承諾」,表示來自其所有父項的所有變更現在都已包含在內。

當然,這是一種權衡:合併需要更仔細的分支管理。以下小節討論了重點。

晉級

當給定的功能從實驗性變為穩定時,它也會在軟體的相應分支之間「晉級」。git.git 使用以下「整合分支」

  • maint 追蹤應該進入下一個「維護版本」的提交,即上次發布的穩定版本的更新;

  • master 追蹤應該進入下一個版本的提交;

  • next 旨在作為一個測試分支,用於測試 master 的穩定性主題。

還有第四個官方分支,其使用方式略有不同

  • seen(維護人員看到的修補程式)是一個整合分支,用於尚未完全準備好包含的內容(請參閱下方的「整合分支」)。

這四個分支中的每一個通常都是上面一個分支的直接後代。

從概念上講,功能進入不穩定的分支(通常是 nextseen),一旦被認為足夠穩定,就會「晉級」到 master 以進行下一個版本。

向上合併

以上討論的「向下晉級」無法透過實際向下合併來完成,因為那會將不穩定分支上的所有變更合併到穩定分支中。因此,以下規則:

規則:向上合併

始終將您的修復提交到需要它們的最舊受支援分支。然後(定期)將整合分支向上合併到彼此之間。

這給予修復一個非常受控的流程。如果您注意到您已將修復套用至例如 master,而該修復在 maint 中也是必需的,則您需要將其向下挑選 (cherry-pick)(使用 git-cherry-pick[1])。這會發生幾次,除非您非常頻繁地執行此操作,否則不必擔心。

主題分支

任何重要的功能都需要多個修補程式才能實現,並且在其生命週期中可能會獲得額外的錯誤修復或改進。

直接在整合分支上提交所有內容會導致許多問題:錯誤的提交無法復原,因此必須逐個還原,這會在您忘記還原一組變更的一部分時產生令人困惑的歷史記錄和進一步的錯誤潛力。並行工作會混合變更,造成進一步的混亂。

使用「主題分支」可以解決這些問題。此名稱不言自明,但有一個來自上述「向上合併」規則的注意事項

規則:主題分支

為每個主題(功能、錯誤修復等)建立一個側邊分支。在您最終想要將其合併到的最舊整合分支處建立分支。

然後,許多事情可以非常自然地完成

  • 要將功能/錯誤修復引入整合分支,只需合併它。如果在此期間主題進一步發展,請再次合併。(請注意,您不一定必須首先將其合併到最舊的整合分支。例如,您可以先將錯誤修復合併到 next,給予它一些測試時間,並在您知道它穩定時合併到 maint。)

  • 如果您發現您需要來自 other 分支的新功能才能繼續處理您的主題,請將 other 合併到 topic。(但是,不要「僅僅習慣性地」執行此操作,請參閱下文。)

  • 如果您發現您分支了錯誤的分支並且想要將其「退回時間」,請使用 git-rebase[1]

請注意,最後一點與其他兩點衝突:已在其他地方合併的主題不應重新設定基底 (rebase)。請參閱 git-rebase[1] 中關於「從上游重新設定基底中復原」的章節。

我們應該指出,「習慣性地」(沒有真正理由地定期)將整合分支合併到您的主題中,並且因此定期將任何上游內容合併到任何下游內容中是令人不快的

規則:僅在明確定義的時間點合併到下游

除非有充分的理由,否則不要合併到下游:上游 API 變更會影響您的分支;您的分支不再能乾淨地合併到上游;等等。

否則,已合併的主題會突然包含多個(良好區隔的)變更。許多由此產生的小型合併會極大地混亂歷史記錄。任何稍後調查文件歷史記錄的人都必須找出該合併是否影響了開發中的主題。上游甚至可能會無意中被合併到「更穩定」的分支中。等等。

拋棄式整合

如果您遵循了最後一段,您現在將擁有許多小型主題分支,並且偶爾會想知道它們如何交互作用。也許合併它們的結果甚至不起作用?但另一方面,我們想避免將它們合併到任何「穩定」的位置,因為這種合併不容易還原。

當然,解決方案是進行可以還原的合併:合併到拋棄式分支中。

規則:拋棄式整合分支

為了測試多個主題的交互作用,請將它們合併到拋棄式分支中。您絕不能以此分支為基礎進行任何工作!

如果您(非常)清楚地表明此分支將在測試後立即刪除,您甚至可以發布此分支,例如讓測試人員有機會使用它,或讓其他開發人員有機會查看他們正在進行的工作是否相容。git.git 有一個名為 seen 的官方拋棄式整合分支。

發行版的分支管理

假設您使用以上討論的合併方法,當您發布專案時,您將需要執行一些額外的分支管理工作。

功能發行版是從 master 分支建立的,因為 master 追蹤應該進入下一個功能發行版的提交。

master 分支應該是 maint 的超集。如果此條件不成立,則 maint 包含一些未包含在 master 中的提交。因此,這些提交所代表的修復將不會包含在您的功能發行版中。

要驗證 master 確實是 maint 的超集,請使用 git log

步驟:驗證 mastermaint 的超集

git log master..maint

此命令不應列出任何提交。否則,請簽出 master 並將 maint 合併到其中。

現在您可以繼續建立功能發行版。將標籤套用至 master 的頂端,以指示發行版本

步驟:發行版標籤

git tag -s -m "Git X.Y.Z" vX.Y.Z master

您需要將新的標籤推送到公開的 Git 伺服器 (請參閱下方的「分散式工作流程」)。這會讓追蹤您專案的其他人員可以使用該標籤。推送也可能會觸發一個 post-update hook,以執行與發布相關的項目,例如建立發布 tarball 和預先格式化的文件頁面。

同樣地,對於維護版本,maint 會追蹤要發布的提交。因此,在上述步驟中,只需標記並推送 maint,而不是 master

功能發布後的維護分支管理

在功能發布後,您需要管理您的維護分支。

首先,如果您希望繼續為最近一次發布之前的功能發布提供維護修復,那麼您必須建立另一個分支來追蹤該先前發布的提交。

為此,目前的維護分支會被複製到另一個以先前發布版本號命名的分支 (例如,maint-X.Y.(Z-1),其中 X.Y.Z 是目前發布的版本)。

步驟:複製 maint

git branch maint-X.Y.(Z-1) maint

現在應該將 maint 分支快轉到新發布的程式碼,以便追蹤目前發布的維護修復。

步驟:將 maint 更新到新發布的版本
  • git checkout maint

  • git merge --ff-only master

如果合併失敗,因為它不是快轉,則可能在功能發布中遺漏了 maint 上的一些修復。如果分支的內容如前一節所述經過驗證,則不會發生這種情況。

功能發布後 next 和 seen 的分支管理

在功能發布後,可以選擇將整合分支 nextmaster 的頂端倒回並使用 next 上存留的主題重新建立。

步驟:倒回並重新建立 next
  • git switch -C next master

  • git merge ai/topic_in_next1

  • git merge ai/topic_in_next2

  • …​

這樣做的好處是 next 的歷史記錄會很乾淨。例如,一些合併到 next 中的主題最初看起來很有希望,但後來發現是不希望的或過早的。在這種情況下,該主題會從 next 中還原,但事實仍然存在於歷史記錄中,它曾經被合併和還原。透過重新建立 next,您可以讓這些主題的另一個化身有機會重新嘗試,而功能發布是這樣做的好時機。

如果您這樣做,則應該發布公開聲明,說明 next 已被倒回並重新建立。

seen 也可以遵循相同的倒回和重新建立過程。由於 seen 是一個用完即丟的分支,如上所述,因此不需要公開聲明。

分散式工作流程

在上一節之後,您應該知道如何管理主題。一般來說,您不會是唯一參與專案的人,因此您必須分享您的工作。

粗略地說,有兩個重要的工作流程:合併和修補程式。重要的區別在於合併工作流程可以傳播完整的歷史記錄,包括合併,而修補程式則不能。這兩種工作流程可以平行使用:在 git.git 中,只有子系統維護人員使用合併工作流程,而其他所有人都發送修補程式。

請注意,維護人員可能會施加限制,例如「Signed-off-by」要求,所有提交/修補程式都必須遵守這些要求才能被納入。有關更多資訊,請參閱您專案的文件。

合併工作流程

合併工作流程的工作方式是在上游和下游之間複製分支。上游可以將貢獻合併到官方歷史記錄中;下游則以官方歷史記錄為基礎進行工作。

有三個主要工具可以用於此

  • git-push[1] 將您的分支複製到遠端儲存庫,通常是所有相關方都可以讀取的儲存庫;

  • git-fetch[1] 將遠端分支複製到您的儲存庫;以及

  • git-pull[1] 一次完成 fetch 和 merge。

請注意最後一點。除非您真的想要合併遠端分支,否則不要使用 git pull

將變更發布出去很容易

步驟:推送/拉取:發布分支/主題

git push <remote> <branch> 並告訴大家他們可以從哪裡提取。

您仍然必須透過其他方式 (例如郵件) 通知其他人。(Git 提供了 git-request-pull[1] 來將預先格式化的拉取請求發送到上游維護人員,以簡化這項任務。)

如果您只是想取得最新版本的整合分支,保持最新狀態也很容易

步驟:推送/拉取:保持最新狀態

使用 git fetch <remote>git remote update 來保持最新狀態。

然後,只需如前所述,從穩定的遠端分支分叉您的主題分支即可。

如果您是維護人員,並且想要將其他人的主題分支合併到整合分支中,他們通常會以郵件方式發送請求來執行此操作。此類請求如下所示

Please pull from
    <URL> <branch>

在這種情況下,git pull 可以一次完成 fetch 和 merge,如下所示。

步驟:推送/拉取:合併遠端主題

git pull <URL> <branch>

有時,維護人員在嘗試從下游拉取變更時可能會遇到合併衝突。在這種情況下,他們可以要求下游進行合併並自行解決衝突 (也許他們會更了解如何解決這些衝突)。這是下游應該從上游合併的少數情況之一。

修補程式工作流程

如果您是以電子郵件形式向上游發送變更的貢獻者,您應該像平常一樣使用主題分支 (請參閱上方)。然後使用 git-format-patch[1] 來產生對應的電子郵件 (強烈建議不要手動格式化它們,因為它會使維護人員的生活更輕鬆)。

步驟:format-patch/am:發布分支/主題
  • git format-patch -M upstream..topic 將它們轉換為預先格式化的修補程式檔案

  • git send-email --to=<收件者> <修補程式>

有關更多使用說明,請參閱 git-format-patch[1]git-send-email[1] 的 manpage。

如果維護人員告訴您您的修補程式不再適用於目前的上游,您將必須重新設定您的主題基礎 (您不能使用合併,因為您無法格式化修補程式合併)

步驟:format-patch/am:保持主題最新

git pull --rebase <URL> <branch>

然後您可以在重新設定基礎期間解決衝突。據推測,您沒有透過郵件以外的方式發布您的主題,因此重新設定基礎沒有問題。

如果您收到這樣的修補程式序列 (作為維護人員,或者也許是收件郵件清單的讀者),請將郵件儲存到檔案中,建立一個新的主題分支,並使用 git am 來匯入提交

步驟:format-patch/am:匯入修補程式

git am < patch

值得指出的一個功能是三向合併,如果您遇到衝突,它可以提供協助:git am -3 將使用修補程式中包含的索引資訊來計算合併基礎。請參閱 git-am[1] 以取得其他選項。

GIT

屬於 git[1] 套件的一部分

scroll-to-top