# gitworkflows
> 原文: [https://git-scm.com/docs/gitworkflows](https://git-scm.com/docs/gitworkflows)
## 名稱
gitworkflows - 使用Git推薦的工作流程概述
## 概要
```
git *
```
## 描述
本文檔試圖記下并激發`git.git`本身使用的一些工作流程元素。一般而言,許多想法都適用,但涉及較少人員的較小項目很少需要完整的工作流程。
我們制定了一套_規則_供快速參考,而散文則試圖激勵他們每個人。不要總是從字面上理解它們;你應該重視你的行動的好理由,而不是像這樣的聯機會。
## 單獨更改
作為一般規則,您應該嘗試將更改拆分為小的邏輯步驟,并提交每個更改。它們應該是一致的,獨立于任何后期提交,通過測試套件等。這使得審查過程更加容易,并且歷史對于以后的檢查和分析更有用,例如 [git-blame [1 ]](https://git-scm.com/docs/git-blame) 和 [git-bisect [1]](https://git-scm.com/docs/git-bisect) 。
要實現這一目標,請嘗試從一開始就將工作分成小步驟。壓縮一些提交總是比將一個大提交分成幾個更容易。不要害怕沿途做太小或不完美的步驟。您可以隨后返回并在發布之前使用`git rebase --interactive`編輯提交。您可以使用`git stash push --keep-index`獨立于其他未提交的更改運行測試套件;參見 [git-stash [1]](https://git-scm.com/docs/git-stash) 的實例部分。
## 管理分支
有兩個主要工具可用于包括從一個分支到另一個分支的更改: [git-merge [1]](https://git-scm.com/docs/git-merge) 和 [git-cherry-pick [1]](https://git-scm.com/docs/git-cherry-pick) 。
合并有許多優點,因此我們嘗試僅使用合并來解決盡可能多的問題。櫻桃采摘仍然偶爾有用;請參閱下面的“向上合并”以獲取示例。
最重要的是,合并工作在分支級別,而櫻桃選擇在提交級別工作。這意味著合并可以輕松地從1次,10次或1000次提交中繼承更改,這反過來意味著工作流程可以更好地擴展到大量貢獻者(和貢獻)。合并也更容易理解,因為合并提交是“承諾”,現在包括來自其所有父項的所有更改。
當然有一個權衡:合并需要更仔細的分支管理。以下小節討論了重點。
### 畢業
由于給定的特征從實驗到穩定,它也在軟件的相應分支之間“畢業”。 `git.git`使用以下_集成分支_:
* _maint_ 跟蹤應該進入下一個“維護版本”的提交,即更新最后發布的穩定版本;
* _master_ 跟蹤應該進入下一個版本的提交;
* _next_ 旨在作為測試主要穩定性主題的測試分支。
第四個官方分支的使用方式略有不同:
* _pu_ (建議更新)是一個集成分支,用于尚未準備好包含的內容(請參閱下面的“集成分支”)。
四個分支中的每一個通常是其上方的分支的直接后代。
從概念上講,一旦被認為足夠穩定,該特征進入不穩定的分支(通常是_下一個_或 _pu_ ),并且“畢業”到_主_用于下一個版本。
### 合并向上
然而,上面討論的“向下分度”不能通過實際向下合并來完成,因為這會將不穩定分支上的_所有_變化合并到穩定分支中。因此如下:
Rule: Merge upwards
始終將修復程序提交到需要它們的最舊的受支持分支。然后(周期性地)將集成分支向上合并到彼此中。
這提供了非常受控制的修復流程。如果您發現自己已將修復程序應用于例如在 _maint_ 中也需要 _master_ ,你需要向下挑選它(使用 [git-cherry-pick [1]](https://git-scm.com/docs/git-cherry-pick) )。這種情況會發生幾次,除非你經常這樣做,否則無需擔心。
### 主題分支
任何重要的功能都需要實現幾個補丁,并且可能在其生命周期內獲得額外的錯誤修正或改進。
直接在集成分支上提交所有內容會導致許多問題:糟糕的提交無法撤消,因此必須逐個還原,這會在您忘記還原一組更改時創建令人困惑的歷史記錄和進一步的錯誤可能性。并行工作混合了變化,造成了進一步的混亂。
使用“主題分支”解決了這些問題。這個名字非常自我解釋,但有一個警告來自上面的“合并向上”規則:
Rule: Topic branches
為每個主題(功能,錯誤修復,...)制作一個側支。在最舊的集成分支中解決它,您最終希望將其合并到其中。
然后很多事情可以很自然地完成:
* 要將功能/錯誤修復納入集成分支,只需將其合并即可。如果主題在此期間進一步發展,請再次合并。 (請注意,您不必首先將其合并到最舊的集成分支。例如,您可以先將錯誤修復合并到_下一個_,給它一些測試時間,并合并到 _maint_ 當你知道它是穩定的。)
* 如果您發現需要分支_其他_的新功能繼續處理您的主題,請將_其他_合并到_主題_。 (但是,不要“習慣性地”這樣做,見下文。)
* 如果您發現分叉錯誤的分支并希望“及時”移動它,請使用 [git-rebase [1]](https://git-scm.com/docs/git-rebase) 。
請注意,最后一點與其他兩個點發生沖突:已在其他位置合并的主題不應重新綁定。請參閱 [git-rebase [1]](https://git-scm.com/docs/git-rebase) 中關于從上游重新恢復的部分。
我們應該指出,“習慣性地”(通常沒有任何實際理由)將整合分支合并到您的主題中 - 并且通過擴展,將任何上游的內容合并到下游的任何內容 - 是不贊成的:
Rule: Merge to downstream only at well-defined points
除非有充分的理由,否則不要合并到下游:上游API更改會影響您的分支;你的分支機構不再干凈地融入上游;等等
否則,合并到的主題突然包含多個(分離良好的)更改。由此導致的許多小合并將極大地混亂歷史。后來調查文件歷史記錄的任何人都必須查明該合并是否會影響開發中的主題。上游甚至可能無意中被合并為“更穩定”的分支。等等。
### 扔掉一體化
如果您遵循最后一段,您現在將擁有許多小主題分支,偶爾會想知道它們是如何交互的。合并它們的結果可能甚至不起作用?但另一方面,我們希望避免將它們合并到任何“穩定”的位置,因為這樣的合并不容易被撤消。
當然,解決方案是進行我們可以撤消的合并:合并到一個扔掉的分支。
Rule: Throw-away integration branches
要測試多個主題的交互,請將它們合并到一個扔掉的分支中。你必須永遠不要在這樣的分支上做任何工作!
如果你(非常)清楚地知道這個分支將在測試后立即被刪除,你甚至可以發布這個分支,例如讓測試人員有機會使用它,或者其他開發人員有機會看看他們是否正在進行的工作將是兼容的。 `git.git`有一個名為 _pu_ 的官方一次性集成分支。
### 發布的分支管理
假設您正在使用上面討論的合并方法,當您發布項目時,您將需要執行一些額外的分支管理工作。
功能發布是從_主_分支創建的,因為_主_跟蹤應該進入下一個功能發布的提交。
_主_分支應該是 _maint_ 的超集。如果此條件不成立,則 _maint_ 包含一些未包含在 _master_ 中的提交。因此,這些提交所代表的修補程序將不會包含在您的功能發行版中。
要驗證 _master_ 確實是 _maint_ 的超集,請使用git log:
Recipe: Verify _master_ is a superset of _maint_
`git log master..maint`
此命令不應列出任何提交。否則,請檢查 _master_ 并將 _maint_ 合并到其中。
現在,您可以繼續創建功能發布。將標簽應用于 _master_ 的尖端,指示發布版本:
Recipe: Release tagging
`git tag -s -m "Git X.Y.Z" vX.Y.Z master`
您需要將新標記推送到公共Git服務器(請參閱下面的“DISTRIBUTED WORKFLOWS”)。這使得其他人可以使用該標簽來跟蹤您的項目。推送還可以觸發更新后掛鉤以執行與發布相關的項目,例如構建發布tar包和預格式化文檔頁面。
同樣,對于維護版本, _maint_ 正在跟蹤要釋放的提交。因此,在上述步驟中,只需標記并按 _maint_ 而不是 _master_ 。
### 功能發布后的維護分支管理
功能發布后,您需要管理維護分支。
首先,如果您希望繼續發布在最近版本之前發布的功能版本的維護修補程序,那么您必須創建另一個分支來跟蹤該先前版本的提交。
為此,將當前維護分支復制到以先前版本號命名的另一個分支(例如,maint-X.Y。(Z-1),其中X.Y.Z是當前版本)。
Recipe: Copy maint
`git branch maint-X.Y.(Z-1) maint`
現在應該將 _maint_ 分支快速轉發到新發布的代碼,以便可以跟蹤當前版本的維護修復:
Recipe: Update maint to new release
* `git checkout maint`
* `git merge --ff-only master`
如果合并失敗,因為它不是快進,那么可能在功能發布中錯過了 _maint_ 的一些修復。如果按照上一節中的描述驗證了分支的內容,則不會發生這種情況。
### 功能發布后的分支管理for next和pu
功能發布后,集成分支 _next_ 可以選擇使用 _next_ 上的幸存主題從 _master_ 的尖端重繞并重建:
Recipe: Rewind and rebuild next
* `git checkout next`
* `git reset --hard master`
* `git merge ai/topic_in_next1`
* `git merge ai/topic_in_next2`
* ...
這樣做的好處是 _next_ 的歷史將是干凈的。例如,合并到_中的一些主題下一個_可能最初看起來很有希望,但后來被發現是不合需要的或者是不成熟的。在這種情況下,主題將從_下一個_中恢復出來,但事實上它仍然存在于曾經合并和還原的歷史中。通過重新創建_下一個_,你可以為這些主題提供另一個版本,以便重試,并且功能發布是歷史上的一個好點。
如果你這樣做,那么你應該做一個公告,表明[??HTG0]下一個被重繞并重建。
對于 _pu_ ,可以遵循相同的倒帶和重建過程。如上所述,由于 _pu_ 是丟棄分支,因此不需要公告。
## 分布式工作流程
在最后一節之后,您應該知道如何管理主題。一般而言,您不會是唯一從事該項目的人,因此您必須分享您的工作。
粗略地說,有兩個重要的工作流程:合并和補丁。重要的區別在于合并工作流可以傳播完整的歷史記錄,包括合并,而補丁則不能。兩個工作流程都可以并行使用:在`git.git`中,只有子系統維護人員使用合并工作流程,而其他人都發送補丁。
請注意,維護者可能會施加限制,例如“簽名”要求,所有提交包含的提交/補丁必須遵守。有關更多信息,請參閱項目文檔。
### 合并工作流程
合并工作流程通過在上游和下游之間復制分支來工作。上游可以將貢獻合并到官方歷史中;下游基地的工作在官方歷史上。
有三種主要工具可用于此:
* [git-push [1]](https://git-scm.com/docs/git-push) 將您的分支復制到遠程存儲庫,通常是一個可供所有相關方讀取的存儲庫;
* [git-fetch [1]](https://git-scm.com/docs/git-fetch) 將遠程分支復制到您的存儲庫;和
* [git-pull [1]](https://git-scm.com/docs/git-pull) 一次性獲取并合并。
注意最后一點。除非你真的想要合并遠程分支,否則_不能_使用 _git pull_ 。
更改很容易:
Recipe: Push/pull: Publishing branches/topics
`git push <remote> <branch>`并告訴每個人他們可以從哪里取。
你仍然需要通過其他方式告訴別人,比如郵件。 (Git提供 [git-request-pull [1]](https://git-scm.com/docs/git-request-pull) 向上游維護者發送預先格式化的拉取請求,以簡化此任務。)
如果您只想獲得集成分支的最新副本,那么保持最新也很容易:
Recipe: Push/pull: Staying up to date
使用`git fetch <remote>`或`git remote update`保持最新。
然后簡單地從穩定的遙控器中分叉您的主題分支,如前所述。
如果您是維護者并希望將其他人的主題分支合并到集成分支,他們通常會通過郵件發送請求。這樣的請求看起來像
```
Please pull from
<url> <branch>
```
在這種情況下, _git pull_ 可以一次性進行獲取和合并,如下所示。
Recipe: Push/pull: Merging remote topics
`git pull <url> <branch>`
有時,維護者在嘗試從下游提取更改時可能會發生合并沖突。在這種情況下,他們可以要求下游進行合并并自己解決沖突(也許他們會更好地了解如何解決它們)。這是下游_應該_從上游合并的罕見情況之一。
### 補丁工作流程
如果您是以電子郵件形式向上游發送更改的貢獻者,您應該像往常一樣使用主題分支(參見上文)。然后使用 [git-format-patch [1]](https://git-scm.com/docs/git-format-patch) 生成相應的電子郵件(強烈建議手動格式化它們,因為它使維護者的生活更輕松)。
Recipe: format-patch/am: Publishing branches/topics
* `git format-patch -M upstream..topic`將它們轉換為預先格式化的補丁文件
* `git send-email --to=<recipient> <patches>`
有關更多使用說明,請參閱 [git-format-patch [1]](https://git-scm.com/docs/git-format-patch) 和 [git-send-email [1]](https://git-scm.com/docs/git-send-email) 聯機幫助頁。
如果維護者告訴您補丁不再適用于當前的上游,則必須重新定義主題(您不能使用合并,因為您無法格式化補丁合并):
Recipe: format-patch/am: Keeping topics up to date
`git pull --rebase <url> <branch>`
然后,您可以在rebase期間修復沖突。大概你沒有通過郵件發布你的主題,所以重新定位它不是問題。
如果您收到這樣的補丁系列(作為維護者,或者作為發送給它的郵件列表的讀者),將郵件保存到文件,創建一個新的主題分支并使用 _git am_ 導入承諾:
Recipe: format-patch/am: Importing patches
`git am < patch`
值得指出的一個特性是三向合并,如果遇到沖突可以提供幫助:`git am -3`將使用補丁中包含的索引信息來確定合并基礎。有關其他選項,請參閱 [git-am [1]](https://git-scm.com/docs/git-am) 。
## 也可以看看
[gittutorial [7]](https://git-scm.com/docs/gittutorial) , [git-push [1]](https://git-scm.com/docs/git-push) , [git-pull [1]](https://git-scm.com/docs/git-pull) , [git-merge [1]](https://git-scm.com/docs/git-merge) , [git-rebase [1]](https://git-scm.com/docs/git-rebase) , [git-format-patch [1]](https://git-scm.com/docs/git-format-patch) , [git-send-email [1]](https://git-scm.com/docs/git-send-email) , [git-am [ 1]](https://git-scm.com/docs/git-am)
## GIT
部分 [git [1]](https://git-scm.com/docs/git) 套件
- git
- git-config
- git-help
- git-init
- git-clone
- git-add
- git-status
- git-diff
- git-commit
- git-reset
- git-rm
- git-mv
- git-branch
- git-checkout
- git-merge
- git-mergetool
- git-log
- git-stash
- git-tag
- git-worktree
- git-fetch
- git-pull
- git-push
- git-remote
- git-submodule
- git-show
- git-log
- git-shortlog
- git-describe
- git-apply
- git-cherry-pick
- git-rebase
- git-revert
- git-bisect
- git-blame
- git-grep
- gitattributes
- giteveryday
- gitglossary
- githooks
- gitignore
- gitmodules
- gitrevisions
- gittutorial
- gitworkflows
- git-am
- git-format-patch
- git-send-email
- git-request-pull
- git-svn
- git-fast-import
- git-clean
- git-gc
- git-fsck
- git-reflog
- git-filter-branch
- git-instaweb
- git-archive
- git-bundle
- git-daemon
- git-update-server-info
- git-cat-file
- git-check-ignore
- git-checkout-index
- git-commit-tree
- git-count-objects
- git-diff-index
- git-for-each-ref
- git-hash-object
- git-ls-files
- git-merge-base
- git-read-tree
- git-rev-list
- git-rev-parse
- git-show-ref
- git-symbolic-ref
- git-update-index
- git-update-ref
- git-verify-pack
- git-write-tree