好文: 如何將程式送給 Open Source 的 Project 與 diff / patch 使用


現在 Open Source 的 Project 很豐富, 想要奉獻心力, 有什麼該注意的事呢?

下述轉載 How to get your code into an open source project 此文的重點(順便加上心得、翻譯等), 再補上一些工具的使用介紹(diff / patch).

  • 註1: 若想直接瞭解 diff / patch 如何使用, 可直接往下找 第 10 點 - 工具和其它外部資源.
  • 註2: 並不是原文翻譯, 只是內容看完, 做點心得筆記, 所以如果要讀詳細的, 還是建議參考原文.

如何將程式送給 Open Source 的 Project

大綱
  1. 早點討論你要做的修改/變更 (Discuss your changes early)
  2. 提交 Patches, 而不是把整包程式送過去 (Submit patches, not lumps of code)
  3. 切割你的 Patches (Split your patches up)
  4. 對目前開發中的最新版本做 Patch (Patch against the latest development version)
  5. 跑過所有測試 (Run any tests)
  6. 更新文件和測試 (Update documentation and tests)
  7. 法律問題 (Legal issues)
  8. Patches 被遺忘 (Lost patches)
  9. 接受拒絕 (Accept rejection)
  10. 工具和其它外部資源 (Nuts and bolts, and external resources)
什麼是 upstream and contributor

首先要參與 Open Source Project 要先瞭解下述兩個名詞:

  • upstream(上游): 此 Project 的管理者、核心團體貢獻者、維護團隊.
  • contributor(貢獻者): 就是你、我 或 任何人, 若有任何建議、修 Bug、皆可回報給上游的人員.

那再來進入正題, 回報時要有哪些注意事項, 上述 10點再做深入一點的描述.

1. 早點討論你要做的修改/變更 (Discuss your changes early)
  • 假如你有需要做某部份的改變, 在修改程式前, 應該先上 mailing lists 去跟 upstream 討論, 並聽聽其它 feedback.
  • 相關參考文件: Release Early, Release Often
2. 提交 Patches, 而不是把整包程式送過去 (Submit patches, not lumps of code)
3. 切割你的 Patches (Split your patches up)
4. 對目前開發中的最新版本做 Patch (Patch against the latest development version)
  • 大家都全力在開發最新的版本, 對最新的版本做 Patch, 開發者們只需要再加點 整合/測試 的時間, 即可合併進去.
  • 相關工具: git-rebase - Forward-port local commits to the updated upstream head
5. 跑過所有測試 (Run any tests)
  • 大多數的 Project 都有包含自動測試的程式, 只要跑 "make check" 或 "make test" 即可, 提交前先確定可以正確跑過所有測試程式.
6. 更新文件和測試 (Update documentation and tests)
  • 不要只是把加強 / 修改的程式加上去, 要記得同時 更新文件 和 測試程式.
7. 法律問題 (Legal issues)
  • 瞭解 License, 而且 若需要取得老闆的授權, 別忘了請示老闆.
8. Patches 被遺忘 (Lost patches)
  • 若 Patches 送上去, 經過一段時間, 都沒有人理(沒有評論/接受/拒絕, 程式也沒有被整入專案中), 像是被忽略或遺忘的話, 再送一次 Patches, 並且再詳細點的描述此 Patch.
9. 接受拒絕 (Accept rejection)

若提交程式、討論不被維護團隊(upstream)接受, 可以有下述兩種選擇:

  1. 對此 Tree 做 Patches (Out of tree patches)

    Tree 指此專案的這分支, 若此分支每次有 Release 新版, 則再對新版做此功能上的 Patch.

  2. 建立此專案的分支 (Forking the project)

    若程式差異太多又不被接受, 可考慮自行建立另外一個專案的分支, 不過有下述幾點要注意:

    • 不要使用一樣或相似的名稱 (don't use the same or a similar name)
    • 要有準備會花比較多的時間去維護 (Do be prepared to invest a large amount of work)
    • 有清楚的目標 (Do have clear goals)
    • 跟之前專案的人員愉快相處 (fork amicably)

相關案例、文件:

10. 工具和其它外部資源 (Nuts and bolts, and external resources)
建立 Patches (Creating patches)

注意:

  • 記得 diff 要加上 -u 的選項(unified diff format)
  • 記得 diff -u oldfile newfile, 舊的檔案在前, 新的檔案在後, 搞混就會懂什麼叫 reversed patch
單一檔案的 Patch
  1. cp file.c file.c.orig # 先將原始檔案備份成 檔名.orig, 再去修改 file.c
  2. diff -u file.c.orig file.c > my-excellent-feature.patch # 將修改過後的檔案與原始檔案做比較
整個目錄的 Patch
  1. 建立原始與準備要修改的目錄
    1. tar zxf foozball-1.0.tar.gz # 解壓縮專案 => foozball-1.0
    2. mv foozball-1.0 foozball-1.0.orig # 改目錄名字 foozball-1.0 => foozball-1.0.orig
    3. tar zxf foozball-1.0.tar.gz # 解壓縮專案 => foozball-1.0
  2. 此時 ls 就可以看到下面兩個目錄

    • foozball-1.0.orig/ # 原始檔案目錄
    • foozball-1.0/ # 修改都在此改
  3. 確定更新的檔案都是在 foozball-1.0, 再做下述產生 patch:

    • diff -ur foozball-1.0.orig foozball-1.0 > four-players.patch # four-players.patch 就完成囉~
將 Patch 加進專案
  1. # 於原始目錄內外都皆可, patch 會自行判斷路徑位置, 若要確定點
  2. # 多個檔案 與 單一檔案執行命令都一樣.
  3. patch -p1 < four-players.patch # 多個檔案 (每次 Patch 一個檔案後, 會問要不要 Patch, -R 就不會再問)
  4. patch -Rp1 < four-players.patch # 多個檔案 (每次 Patch 一個檔案後, 直接問下一個要 Patch 的檔案路徑)
  5. patch -p1 < my-excellent-feature.patch # 單一檔案
  6. 出現

    --------------------------
    |diff -ur test.orig/test.php test/test.php
    |--- test.orig/test.php 2009-01-09 23:07:14.000000000 +0800
    |+++ test/test.php      2009-01-14 22:57:14.769218104 +0800
    --------------------------
    File to patch:

  7. 於 "File to patch:" 輸入: test/test.php (此 Patch 要加在哪個檔案上, 多個檔案問循環繼續問下去)
  8. 跑完即將 Patch 都更新完成.
其它資源
- Version control systems
- Tools for managing sets of patches

Quilt

  • quilt - The scripts allow to manage a series of patches by keeping track of the changes each patch makes. Patches can be applied, un-applied, refreshed, etc.
  • Quilt: An Introduction

Git

  • Git branches (a branch is a sequence of patches) - git rebase --interactive ... to reorder/edit/merge/split change sets, git stash, and much more.

Mercurial

  • Mercurial has a "queues" extension.
Software licenses
其它提交 patches 的注意事項 (Other guidelines on submitting patches)
Authors

關於 Tsung

對新奇的事物都很有興趣, 喜歡簡單的東西, 過簡單的生活.
本篇發表於 Document-Ebook。將永久鏈結加入書籤。

發表迴響