<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # 向一個項目貢獻 描述如何向一個項目貢獻的主要困難在于完成貢獻有很多不同的方式。因為 Git 非常靈活,人們可以通過不同的方式來一起工作,所以描述應該如何貢獻并不是非常準確 - 每一個項目都有一點兒不同。影響因素包括活躍貢獻者的數量、選擇的工作流程、提交權限與可能包含的外部貢獻方法。 第一個影響因素是活躍貢獻者的數量 - 積極地向這個項目貢獻代碼的用戶數量以及他們的貢獻頻率。在許多情況下,你可能會有兩三個開發者一天提交幾次,對于不活躍的項目可能更少。對于大一些的公司或項目,開發者的數量可能會是上千,每天都有成百上千次提交。這很重要,因為隨著開發者越來越多,在確保你的代碼能干凈地應用或輕松地合并時會遇到更多問題。提交的改動可能表現為過時的,也可能在你正在做改動或者等待改動被批準應用時被合并入的工作嚴重損壞。如何保證代碼始終是最新的,并且提交始終是有效的? 下一個影響因素是項目使用的工作流程。它是中心化的嗎,即每一個開發者都對主線代碼有相同的寫入權限?項目是否有一個檢查所有補丁的維護者或整合者?是否所有的補丁是同行評審后批準的?你是否參與了那個過程?是否存在副官系統,你必須先將你的工作提交到上面? 下一個問題是提交權限。是否有項目的寫權限會使向項目貢獻所需的流程有極大的不同。如果沒有寫權限,項目會選擇何種方式接受貢獻的工作?是否甚至有一個如何貢獻的規范?你一次貢獻多少工作?你多久貢獻一次? 所有這些問題都會影響實際如何向一個項目貢獻,以及對你來說哪些工作流程更適合或者可用。我們將會由淺入深,通過一系列用例來講述其中的每一個方面;從這些例子應該能夠建立實際中你需要的特定工作流程。 ## 提交準則 在我們開始查看特定的用例前,這里有一個關于提交信息的快速說明。有一個好的創建提交的準則并且堅持使用會讓與 Git 工作和與其他人協作更容易。Git 項目提供了一個文檔,其中列舉了關于創建提交到提交補丁的若干好的提示 - 可以在 Git 源代碼中的 `Documentation/SubmittingPatches` 文件中閱讀它。 首先,你不會想要把空白錯誤(根據 git help diff 的描述,結合下面給出的圖片,空白錯誤是指行尾的空格、Tab 制表符,和行首空格后跟 Tab 制表符的行為)提交上去。Git 提供了一個簡單的方式來檢查這點 - 在提交前,運行 `git diff --check`,它將會找到可能的空白錯誤并將它們為你列出來。 ![`git diff --check` 的輸出。](https://box.kancloud.cn/2015-10-12_561bcb6ce450b.png) Figure 5-4. `git diff --check` 的輸出 如果在提交前運行那個命令,可以知道提交中是否包含可能會使其他開發者惱怒的空白問題。 接下來,嘗試讓每一個提交成為一個邏輯上的獨立變更集。如果可以,嘗試讓改動可以理解 - 不要在整個周末編碼解決五個問題,然后在周一時將它們提交為一個巨大的提交。即使在周末期間你無法提交,在周一時使用暫存區域將你的工作最少拆分為每個問題一個提交,并且為每一個提交附帶一個有用的信息。如果其中一些改動修改了同一個文件,嘗試使用 `git add --patch` 來部分暫存文件(在 [“交互式暫存”](#) 中有詳細介紹)。不管你做一個或五個提交,只要所有的改動是在同一時刻添加的,項目分支末端的快照就是獨立的,使同事開發者必須審查你的改動時盡量讓事情容易些。當你之后需要時這個方法也會使拉出或還原一個變更集更容易些。[“重寫歷史”](#) 描述了重寫歷史與交互式暫存文件的若干有用的 Git 技巧 - 在將工作發送給其他人前使用這些工具來幫助生成一個干凈又易懂的歷史。 最后一件要牢記的事是提交信息。有一個創建優質提交信息的習慣會使 Git 的使用與協作容易的多。一般情況下,信息應當以少于 50 個字符(25個漢字)的單行開始且簡要地描述變更,接著是一個空白行,再接著是一個更詳細的解釋。Git 項目要求一個更詳細的解釋,包括做改動的動機和它的實現與之前行為的對比 - 這是一個值得遵循的好規則。在這些信息中使用現在時態祈使語氣也是一個好想法。換句話說,使用命令。使用 “Add tests for.” 而不是 “I added tests for” 或 “Adding tests for,”。這里是一份最初由 Tim Pope 寫的模板: ~~~ 修改的摘要(50 個字符或更少) 如果必要的話,加入更詳細的解釋文字。在 大概 72 個字符的時候換行。在某些情形下, 第一行被當作一封電子郵件的標題,剩下的 文本作為正文。分隔摘要與正文的空行是 必須的(除非你完全省略正文);如果你將 兩者混在一起,那么類似變基等工具無法 正常工作。 空行接著更進一步的段落。 - 句號也是可以的。 - 項目符號可以使用典型的連字符或星號 前面一個空格,之間用空行隔開, 但是可以依據不同的慣例有所不同。 ~~~ 如果你所有的提交信息看起來都像這樣,對你與跟你工作在一起的其他開發者來說事情會變得非常容易。Git 項目有一個良好格式化的提交信息 - 嘗試在那兒運行 `git log --no-merges` 來看看漂亮的格式化的項目提交歷史像什么樣。 在接下來的例子中,以及貫穿本書大部分,出于簡潔性的原因本書不會有像這樣漂亮格式的信息;相反,我們使用 `-m` 選項的 `git commit`。照我們說的做,而不是照我們做的做。 ## 私有小型團隊 你可能會遇到的最簡單的配置是有一兩個其他開發者的私有項目。“私有” 在這個上下文中,意味著閉源 - 不可以從外面的世界中訪問到。你和其他的開發者都有倉庫的推送權限。 在這個環境下,可以采用一個類似使用 Subversion 或其他集中式的系統時會使用的工作流程。依然可以得到像離線提交、非常容易地新建分支與合并分支等高級功能,但是工作流程可以是很簡單的;主要的區別是合并發生在客戶端這邊而不是在提交時發生在服務器那邊。讓我們看看當兩個開發者在一個共享倉庫中一起工作時會是什么樣子。第一個開發者,John,克隆了倉庫,做了改動,然后本地提交。(為了縮短這些例子長度,協議信息已被替換為 `...`。) ~~~ # John's Machine $ git clone john@githost:simplegit.git Initialized empty Git repository in /home/john/simplegit/.git/ ... $ cd simplegit/ $ vim lib/simplegit.rb $ git commit -am 'removed invalid default value' [master 738ee87] removed invalid default value 1 files changed, 1 insertions(+), 1 deletions(-) ~~~ 第二個開發者,Jessica,做了同樣的事情 - 克隆倉庫并提交了一個改動: ~~~ # Jessica's Machine $ git clone jessica@githost:simplegit.git Initialized empty Git repository in /home/jessica/simplegit/.git/ ... $ cd simplegit/ $ vim TODO $ git commit -am 'add reset task' [master fbff5bc] add reset task 1 files changed, 1 insertions(+), 0 deletions(-) ~~~ 現在,Jessica 把她的工作推送到服務器上: ~~~ # Jessica's Machine $ git push origin master ... To jessica@githost:simplegit.git 1edee6b..fbff5bc master -> master ~~~ John 也嘗試推送他的改動: ~~~ # John's Machine $ git push origin master To john@githost:simplegit.git ! [rejected] master -> master (non-fast forward) error: failed to push some refs to 'john@githost:simplegit.git' ~~~ 不允許 John 推送是因為在同一時間 Jessica 已經推送了。如果之前習慣于用 Subversion 那么理解這點特別重要,因為你會注意到兩個開發者并沒有編輯同一個文件。盡管 Subversion 會對編輯的不同文件在服務器上自動進行一次合并,但 Git 要求你在本地合并提交。John 必須抓取 Jessica 的改動并合并它們,才能被允許推送。 ~~~ $ git fetch origin ... From john@githost:simplegit + 049d078...fbff5bc master -> origin/master ~~~ 在這個時候,John 的本地倉庫看起來像這樣: ![John 的分叉歷史。](https://box.kancloud.cn/2015-10-12_561bcb6d03b1a.png) Figure 5-5. John 的分叉歷史 John 有一個引用指向 Jessica 推送上去的改動,但是他必須將它們合并入自己的工作中之后才能被允許推送。 ~~~ $ git merge origin/master Merge made by recursive. TODO | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) ~~~ 合并進行地很順利 - John 的提交歷史現在看起來像這樣: ![合并了 `origin/master` 之后 John 的倉庫。](https://box.kancloud.cn/2015-10-12_561bcb6d1b1e4.png) Figure 5-6. 合并了 `origin/master` 之后 John 的倉庫 現在,John 可以測試代碼,確保它依然正常工作,然后他可以把合并的新工作推送到服務器上: ~~~ $ git push origin master ... To john@githost:simplegit.git fbff5bc..72bbc59 master -> master ~~~ 最終,John 的提交歷史看起來像這樣: ![推送到 `origin` 服務器后 John 的歷史。](https://box.kancloud.cn/2015-10-12_561bcb6d2a086.png) Figure 5-7. 推送到 `origin` 服務器后 John 的歷史 在此期間,Jessica 在一個特性分支上工作。她創建了一個稱作 `issue54` 的特性分支并且在那個分支上做了三次提交。她還沒有抓取 John 的改動,所以她的提交歷史看起來像這樣: ![Jessica 的特性分支。](https://box.kancloud.cn/2015-10-12_561bcb6d383ea.png) Figure 5-8. Jessica 的特性分支 Jessica 想要與 John 同步,所以她進行了抓取操作: ~~~ # Jessica's Machine $ git fetch origin ... From jessica@githost:simplegit fbff5bc..72bbc59 master -> origin/master ~~~ 那會同時拉取 John 推送的工作。Jessica 的歷史現在看起來像這樣: ![抓取 John 的改動后 Jessica 的歷史。](https://box.kancloud.cn/2015-10-12_561bcb6d46aaf.png) Figure 5-9. 抓取 John 的改動后 Jessica 的歷史 Jessica 認為她的特性分支已經準備好了,但是她想要知道必須合并什么進入她的工作才能推送。她運行 `git log` 來找出: ~~~ $ git log --no-merges issue54..origin/master commit 738ee872852dfaa9d6634e0dea7a324040193016 Author: John Smith <jsmith@example.com> Date: Fri May 29 16:01:27 2009 -0700 removed invalid default value ~~~ `issue54..origin/master` 語法是一個日志過濾器,要求 Git 只顯示所有在后面分支(在本例中是 `origin/master`)但不在前面分支(在本例中是 `issue54`)的提交的列表。我們將會在 [“提交區間”](#) 中詳細介紹這個語法。 目前,我們可以從輸出中看到有一個 John 生成的但是 Jessica 還沒有合并入的提交。如果她合并 `origin/master`,也就是說將會修改她的本地工作的那個單個提交。 現在,Jessica 可以合并她的特性工作到她的 master 分支,合并 John 的工作(`origin/master`)進入她的 `master` 分支,然后再次推送回服務器。首先,為了整合所有這些工作她切換回她的 master 分支。 ~~~ $ git checkout master Switched to branch 'master' Your branch is behind 'origin/master' by 2 commits, and can be fast-forwarded. ~~~ 她既可以先合并 `origin/master` 也可以先合并 `issue54` - 它們都是上游,所以順序并沒有關系。不論她選擇的順序是什么最終的結果快照是完全一樣的;只是歷史會有一點輕微的區別。她選擇先合并入 `issue54`: ~~~ $ git merge issue54 Updating fbff5bc..4af4298 Fast forward README | 1 + lib/simplegit.rb | 6 +++++- 2 files changed, 6 insertions(+), 1 deletions(-) ~~~ 沒有發生問題;如你所見它是一次簡單的快進。現在 Jessica 合并入 John 的工作(`origin/master`): ~~~ $ git merge origin/master Auto-merging lib/simplegit.rb Merge made by recursive. lib/simplegit.rb | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) ~~~ 每一個文件都干凈地合并了,Jessica 的歷史看起來像這樣: ![合并了 John 的改動后 Jessica 的歷史。](https://box.kancloud.cn/2015-10-12_561bcb6d5488b.png) Figure 5-10. 合并了 John 的改動后 Jessica 的歷史 現在 `origin/master` 是可以從 Jessica 的 `master` 分支到達的,所以她應該可以成功地推送(假設同一時間 John 并沒有再次推送): ~~~ $ git push origin master ... To jessica@githost:simplegit.git 72bbc59..8059c15 master -> master ~~~ 每一個開發者都提交了幾次并成功地合并了其他人的工作。 ![推送所有的改動回服務器后 Jessica 的歷史。](https://box.kancloud.cn/2015-10-12_561bcb6d6688e.png) Figure 5-11. 推送所有的改動回服務器后 Jessica 的歷史 這是一個最簡單的工作流程。你通常在一個特性分支工作一會兒,當它準備好整合時合并回你的 master 分支。當想要共享工作時,將其合并回你自己的 master 分支,如果有改動的話然后抓取并合并 `origin/master`,最終推送到服務器上的 `master` 分支。通常順序像這樣: ![一個簡單的多人 Git 工作流程的通常事件順序。](https://box.kancloud.cn/2015-10-12_561bcb6d7719b.png) Figure 5-12. 一個簡單的多人 Git 工作流程的通常事件順序 ## 私有管理團隊 在接下來的情形中,你會看到大型私有團隊中貢獻者的角色。在你將學習到的這種工作環境中,小組基于特性進行協作,這些團隊的貢獻將會由其他人整合。 讓我們假設 John 與 Jessica 在一個特性上工作,同時 Jessica 與 Josie 在第二個特性上工作。在本例中,公司使用了一種整合-管理者工作流程,獨立小組的工作只能被特定的工程師整合,主倉庫的 `master` 分支只能被那些工程師更新。在這種情況下,所有的工作都是在基于團隊的分支上完成的并且稍后會被整合者拉到一起。 因為 Jessica 在兩個特性上工作,并且平行地與兩個不同的開發者協作,讓我們跟隨她的工作流程。假設她已經克隆了倉庫,首先決定在 `featureA` 上工作。她為那個特性創建了一個新分支然后在那做了一些工作: ~~~ # Jessica's Machine $ git checkout -b featureA Switched to a new branch 'featureA' $ vim lib/simplegit.rb $ git commit -am 'add limit to log function' [featureA 3300904] add limit to log function 1 files changed, 1 insertions(+), 1 deletions(-) ~~~ 在這個時候,她需要將工作共享給 John,所以她推送了 `featureA` 分支的提交到服務器上。Jessica 沒有 `master` 分支的推送權限 - 只有整合者有 - 所以為了與 John 協作必須推送另一個分支。 ~~~ $ git push -u origin featureA ... To jessica@githost:simplegit.git * [new branch] featureA -> featureA ~~~ Jessica 向 John 發郵件告訴他已經推送了一些工作到 `featureA` 分支現在可以看一看。當她等待 John 的反饋時,Jessica 決定與 Josie 開始在 `featureB` 上工作。為了開始工作,她基于服務器的 `master` 分支開始了一個新分支。 ~~~ # Jessica's Machine $ git fetch origin $ git checkout -b featureB origin/master Switched to a new branch 'featureB' ~~~ 現在,Jessica 在 `featureB` 分支上創建了幾次提交: ~~~ $ vim lib/simplegit.rb $ git commit -am 'made the ls-tree function recursive' [featureB e5b0fdc] made the ls-tree function recursive 1 files changed, 1 insertions(+), 1 deletions(-) $ vim lib/simplegit.rb $ git commit -am 'add ls-files' [featureB 8512791] add ls-files 1 files changed, 5 insertions(+), 0 deletions(-) ~~~ Jessica 的倉庫看起來像這樣: ![Jessica 的初始提交歷史。](https://box.kancloud.cn/2015-10-12_561bcb6d89819.png) Figure 5-13. Jessica 的初始提交歷史 她準備好推送工作了,但是一封來自 Josie 的郵件告知一些初始工作已經被推送到服務器上的 `featureBee` 上了。Jessica 在能推送到服務器前首先需要將那些改動與她自己的合并。然后她可以通過 `git fetch` 抓取 Josie 的改動: ~~~ $ git fetch origin ... From jessica@githost:simplegit * [new branch] featureBee -> origin/featureBee ~~~ Jessica 現在可以通過 `git merge` 將其合并到她做的工作中: ~~~ $ git merge origin/featureBee Auto-merging lib/simplegit.rb Merge made by recursive. lib/simplegit.rb | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) ~~~ 有點兒問題 - 她需要將在 `featureB` 分支上合并的工作推送到服務器上的 `featureBee` 分支。她可以通過指定本地分支加上冒號(:)加上遠程分支給 `git push` 命令來這樣做: ~~~ $ git push -u origin featureB:featureBee ... To jessica@githost:simplegit.git fba9af8..cd685d1 featureB -> featureBee ~~~ 這稱作一個 *引用規格*。查看 [“引用規格”](#) 了解關于 Git 引用規格與通過它們可以做的不同的事情的詳細討論。也要注意 `-u` 標記;這是 `--set-upstream` 的簡寫,該標記會為之后輕松地推送與拉取配置分支。 緊接著,John 發郵件給 Jessica 說他已經推送了一些改動到 `featureA` 分支并要求她去驗證它們。她運行一個 `git fetch` 來拉取下那些改動: ~~~ $ git fetch origin ... From jessica@githost:simplegit 3300904..aad881d featureA -> origin/featureA ~~~ 然后,通過 `git log` 她可以看到哪些發生了改變: ~~~ $ git log featureA..origin/featureA commit aad881d154acdaeb2b6b18ea0e827ed8a6d671e6 Author: John Smith <jsmith@example.com> Date: Fri May 29 19:57:33 2009 -0700 changed log output to 30 from 25 ~~~ 最終,她合并 John 的工作到她自己的 `featureA` 分支: ~~~ $ git checkout featureA Switched to branch 'featureA' $ git merge origin/featureA Updating 3300904..aad881d Fast forward lib/simplegit.rb | 10 +++++++++- 1 files changed, 9 insertions(+), 1 deletions(-) ~~~ Jessica 想要輕微調整一些東西,所以她再次提交然后將其推送回服務器: ~~~ $ git commit -am 'small tweak' [featureA 774b3ed] small tweak 1 files changed, 1 insertions(+), 1 deletions(-) $ git push ... To jessica@githost:simplegit.git 3300904..774b3ed featureA -> featureA ~~~ Jessica 的提交歷史現在看起來像這樣: ![在一個特性分支提交后 Jessica 的歷史。](https://box.kancloud.cn/2015-10-12_561bcb6d9998d.png) Figure 5-14. 在一個特性分支提交后 Jessica 的歷史 Jessica、Josie 與 John 通知整合者在服務器上的 `featureA` 與 `featureBee` 分支準備好整合到主線中了。在整合者合并這些分支到主線后,一次抓取會拿下來一個新的合并提交,使歷史看起來像這樣: ![合并了 Jessica 的兩個特性分支后她的歷史。](https://box.kancloud.cn/2015-10-12_561bcb6db28e5.png) Figure 5-15. 合并了 Jessica 的兩個特性分支后她的歷史 許多團隊切換到 Git 是因為這一允許多個團隊并行工作、并在之后合并不同工作的能力。團隊中更小一些的子小組可以通過遠程分支協作而不必影響或妨礙整個團隊的能力是 Git 的一個巨大優勢。在這兒看到的工作流程順序類似這樣: ![這種管理團隊工作流程的基本順序。](https://box.kancloud.cn/2015-10-12_561bcb6dc4d97.png) Figure 5-16. 這種管理團隊工作流程的基本順序 ## 派生的公開項目 向公開項目做貢獻有一點兒不同。因為沒有權限直接更新項目的分支,你必須用其他辦法將工作給維護者。第一個例子描述在支持簡單派生的 Git 托管上使用派生來做貢獻。許多托管站點支持這個功能(包括 GitHub、BitBucket、Google Code、repo.or.cz 等等),許多項目維護者期望這種風格的貢獻。下一節會討論偏好通過郵件接受貢獻補丁的項目。 首先,你可能想要克隆主倉庫,為計劃貢獻的補丁或補丁序列創建一個特性分支,然后在那兒做工作。順序看起來基本像這樣: ~~~ $ git clone (url) $ cd project $ git checkout -b featureA # (work) $ git commit # (work) $ git commit ~~~ 你可能會想要使用 `rebase -i` 來將工作壓縮成一個單獨的提交,或者重排提交中的工作使補丁更容易被維護者審核 - 查看 [“重寫歷史”](#) 了解關于交互式變基的更多信息。 當你的分支工作完成后準備將其貢獻回維護者,去原始項目中然后點擊 “Fork” 按鈕,創建一份自己的可寫的項目派生倉庫。然后需要添加這個新倉庫 URL 為第二個遠程倉庫,在本例中稱作 `myfork`: ~~~ $ git remote add myfork (url) ~~~ 然后需要推送工作到上面。相對于合并到主分支再推送上去,推送你正在工作的特性分支到倉庫上更簡單。原因是工作如果不被接受或者是被揀選的,就不必回退你的 master 分支。如果維護者合并、變基或揀選你的工作,不管怎樣你最終會通過拉取他們的倉庫找回來你的工作。 ~~~ $ git push -u myfork featureA ~~~ 當工作已經被推送到你的派生后,你需要通知維護者。這通常被稱作一個拉取請求(pull request),你既可以通過網站生成它 - GitHub 有它自己的 Pull Request 機制,我們將會在 [Chapter?6](#) 介紹 - 也可以運行 `git request-pull` 命令然后手動地將輸出發送電子郵件給項目的維護者。 `request-pull` 命令接受特性分支拉入的基礎分支,以及它們拉入的 Git 倉庫 URL,輸出請求拉入的所有修改的總結。例如,Jessica 想要發送給 John 一個拉取請求,她已經在剛剛推送的分支上做了兩次提交。她可以運行這個: ~~~ $ git request-pull origin/master myfork The following changes since commit 1edee6b1d61823a2de3b09c160d7080b8d1b3a40: John Smith (1): added a new function are available in the git repository at: git://githost/simplegit.git featureA Jessica Smith (2): add limit to log function change log output to 30 from 25 lib/simplegit.rb | 10 +++++++++- 1 files changed, 9 insertions(+), 1 deletions(-) ~~~ 這個輸出可以被發送給維護者 - 它告訴他們工作是從哪個分支開始、歸納的提交與從哪里拉入這些工作。 在一個你不是維護者的項目上,通常有一個總是跟蹤 `origin/master` 的 `master` 分支會很方便,在特性分支上做工作是因為如果它們被拒絕時你可以輕松地丟棄。如果同一時間主倉庫移動了然后你的提交不再能干凈地應用,那么使工作主題獨立于特性分支也會使你變基(rebase)工作時更容易。例如,你想要提供第二個特性工作到項目,不要繼續在剛剛推送的特性分支上工作 - 從主倉庫的 `master` 分支重新開始: ~~~ $ git checkout -b featureB origin/master # (work) $ git commit $ git push myfork featureB # (email maintainer) $ git fetch origin ~~~ 現在,每一個特性都保存在一個貯藏庫中 - 類似于補丁隊列 - 可以重寫、變基與修改而不會讓特性互相干涉或互相依賴,像這樣: ![`featureB` 的初始提交歷史。](https://box.kancloud.cn/2015-10-12_561bcb6dded99.png) Figure 5-17. `featureB` 的初始提交歷史 假設項目維護者已經拉取了一串其他補丁,然后嘗試拉取你的第一個分支,但是沒有干凈地合并。在這種情況下,可以嘗試變基那個分支到 `origin/master` 的頂部,為維護者解決沖突,然后重新提交你的改動: ~~~ $ git checkout featureA $ git rebase origin/master $ git push -f myfork featureA ~~~ 這樣會重寫你的歷史,現在看起來像是 [Figure?5-18](#) ![`featureA` 工作之后的提交歷史。](https://box.kancloud.cn/2015-10-12_561bcb6def941.png) Figure 5-18. `featureA` 工作之后的提交歷史 因為你將分支變基了,所以必須為推送命令指定 `-f` 選項,這樣才能將服務器上有一個不是它的后代的提交的 `featureA` 分支替換掉。一個替代的選項是推送這個新工作到服務器上的一個不同分支(可能稱作 `featureAv2`)。 讓我們看一個更有可能的情況:維護者看到了你的第二個分支上的工作并且很喜歡其中的概念,但是想要你修改一下實現的細節。你也可以利用這次機會將工作基于項目現在的 `master` 分支。你從現在的 `origin/master` 分支開始一個新分支,在那兒壓縮 `featureB` 的改動,解決任何沖突,改變實現,然后推送它為一個新分支。 ~~~ $ git checkout -b featureBv2 origin/master $ git merge --no-commit --squash featureB # (change implementation) $ git commit $ git push myfork featureBv2 ~~~ `--squash` 選項接受被合并的分支上的所有工作,并將其壓縮至一個變更集,使倉庫變成一個真正的合并發生的狀態,而不會真的生成一個合并提交。這意味著你的未來的提交將會只有一個父提交,并允許你引入另一個分支的所有改動,然后在記錄一個新提交前做更多的改動。同樣 `--no-commit` 選項在默認合并過程中可以用來延遲生成合并提交。 現在你可以給維護者發送一條消息,表示你已經做了要求的修改然后他們可以在你的 `featureBv2` 分支上找到那些改動。 ![`featureBv2` 工作之后的提交歷史。](https://box.kancloud.cn/2015-10-12_561bcb6e0922e.png) Figure 5-19. `featureBv2` 工作之后的提交歷史 ## 通過郵件的公開項目 許多項目建立了接受補丁的流程 - 需要檢查每一個項目的特定規則,因為它們之間有區別。因為有幾個歷史悠久的、大型的項目會通過一個開發者的郵件列表接受補丁,現在我們將會通過一個例子來演示。 工作流程與之前的用例是類似的 - 你為工作的每一個補丁序列創建特性分支。區別是如何提交它們到項目中。生成每一個提交序列的電子郵件版本然后郵寄它們到開發者郵件列表,而不是派生項目然后推送到你自己的可寫版本。 ~~~ $ git checkout -b topicA # (work) $ git commit # (work) $ git commit ~~~ 現在有兩個提交要發送到郵件列表。使用 `git format-patch` 來生成可以郵寄到列表的 mbox 格式的文件 - 它將每一個提交轉換為一封電子郵件,提交信息的第一行作為主題,剩余信息與提交引入的補丁作為正文。它有一個好處是是使用 `format-patch` 生成的一封電子郵件應用的提交正確地保留了所有的提交信息。 ~~~ $ git format-patch -M origin/master 0001-add-limit-to-log-function.patch 0002-changed-log-output-to-30-from-25.patch ~~~ `format-patch` 命令打印出它創建的補丁文件名字。`-M` 開關告訴 Git 查找重命名。文件最后看起來像這樣: ~~~ $ cat 0001-add-limit-to-log-function.patch From 330090432754092d704da8e76ca5c05c198e71a8 Mon Sep 17 00:00:00 2001 From: Jessica Smith <jessica@example.com> Date: Sun, 6 Apr 2008 10:17:23 -0700 Subject: [PATCH 1/2] add limit to log function Limit log functionality to the first 20 --- lib/simplegit.rb | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/lib/simplegit.rb b/lib/simplegit.rb index 76f47bc..f9815f1 100644 --- a/lib/simplegit.rb +++ b/lib/simplegit.rb @@ -14,7 +14,7 @@ class SimpleGit end def log(treeish = 'master') - command("git log #{treeish}") + command("git log -n 20 #{treeish}") end def ls_tree(treeish = 'master') -- 2.1.0 ~~~ 也可以編輯這些補丁文件為郵件列表添加更多不想要在提交信息中顯示出來的信息。如果在 `---` 行與補丁開頭(`diff --git` 行)之間添加文本,那么開發者就可以閱讀它;但是應用補丁時會排除它。 為了將其郵寄到郵件列表,你既可以將文件粘貼進電子郵件客戶端,也可以通過命令行程序發送它。粘貼文本經常會發生格式化問題,特別是那些不會合適地保留換行符與其他空白的 “更聰明的” 客戶端。幸運的是,Git 提供了一個工具幫助你通過 IMAP 發送正確格式化的補丁,這可能對你更容易些。我們將會演示如何通過 Gmail 發送一個補丁,它正好是我們所知最好的郵件代理;可以在之前提到的 Git 源代碼中的 `Documentation/SubmittingPatches` 文件的最下面了解一系列郵件程序的詳細指令。 首先,需要在 `~/.gitconfig` 文件中設置 imap 區塊。可以通過一系列的 `git config` 命令來分別設置每一個值,或者手動添加它們,不管怎樣最后配置文件應該看起來像這樣: ~~~ [imap] folder = "[Gmail]/Drafts" host = imaps://imap.gmail.com user = user@gmail.com pass = p4ssw0rd port = 993 sslverify = false ~~~ 如果 IMAP 服務器不使用 SSL,最后兩行可能沒有必要,host 的值會是 `imap://` 而不是 `imaps://`。當那些設置完成后,可以使用 `git imap-send` 將補丁序列放在特定 IMAP 服務器的 Drafts 文件夾中: ~~~ $ cat *.patch |git imap-send Resolving imap.gmail.com... ok Connecting to [74.125.142.109]:993... ok Logging in... sending 2 messages 100% (2/2) done ~~~ 在這個時候,你應該能夠到 Drafts 文件夾中,修改收件人字段為想要發送補丁的郵件列表,可能需要抄送給維護者或負責那個部分的人,然后發送。 你也可以通過一個 SMTP 服務器發送補丁。同之前一樣,你可以通過一系列的 `git config` 命令來分別設置選項,或者你可以手動地將它們添加到你的 `~/.gitconfig` 文件的 sendmail 區塊: ~~~ [sendemail] smtpencryption = tls smtpserver = smtp.gmail.com smtpuser = user@gmail.com smtpserverport = 587 ~~~ 當這完成后,你可以使用 `git send-email` 發送你的補丁: ~~~ $ git send-email *.patch 0001-added-limit-to-log-function.patch 0002-changed-log-output-to-30-from-25.patch Who should the emails appear to be from? [Jessica Smith <jessica@example.com>] Emails will be sent from: Jessica Smith <jessica@example.com> Who should the emails be sent to? jessica@example.com Message-ID to be used as In-Reply-To for the first email? y ~~~ 然后,對于正在發送的每一個補丁,Git 會吐出這樣的一串日志信息: ~~~ (mbox) Adding cc: Jessica Smith <jessica@example.com> from \line 'From: Jessica Smith <jessica@example.com>' OK. Log says: Sendmail: /usr/sbin/sendmail -i jessica@example.com From: Jessica Smith <jessica@example.com> To: jessica@example.com Subject: [PATCH 1/2] added limit to log function Date: Sat, 30 May 2009 13:29:15 -0700 Message-Id: <1243715356-61726-1-git-send-email-jessica@example.com> X-Mailer: git-send-email 1.6.2.rc1.20.g8c5b.dirty In-Reply-To: <y> References: <y> Result: OK ~~~ ## 總結 這個部分介紹了處理可能會遇到的幾個迥然不同類型的 Git 項目的一些常見的工作流程,介紹了幫助管理這個過程的一些新工具。接下來,你會了解到如何在貢獻的另一面工作:維護一個 Git 項目。你將會學習如何成為一個仁慈的獨裁者或整合管理者。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看