小巧、快速、可靠。
任選三項。
SQLite 為何不使用 Git

1. 簡介

SQLite 不使用 Git 版本控制系統。SQLite 使用 Fossil,這是一個專門設計和編寫來支援 SQLite 的版本控制系統。

人們常想知道為何 SQLite 不像其他人一樣使用 Git 版本控制系統。本文嘗試回答這個問題。此外,在 第 3 節 中,本文提供提示給 Git 使用者,說明他們如何輕鬆存取 SQLite 原始碼。

本文不是 Fossil 和 Git 的比較。請參閱 https://fossil-scm.org/fossil/doc/trunk/www/fossil-v-git.wiki,了解這兩個系統的比較。其他第三方比較也可用 - 使用搜尋引擎即可找到。

本文並非主張您應該放棄 Git,改用其他專案。您可以使用任何您想要的版本控制系統。如果您對 Git 非常滿意,那就繼續使用 Git。但是,如果 Git 無法順利運作,或者您想知道是否能有所改善,或是否有更好的選擇,那麼不妨試著了解以下觀點。運用由此獲得的見解,找出或撰寫一個不同且更好的版本控制系統,或只是對 Git 本身進行改進。

1.1. 編輯

本文已多次修訂,以改善清晰度、解決疑慮和誤解,以及修正錯誤。本文的完整編輯歷程可見於 https://sqlite.dev.org.tw/docsrc/finfo/pages/whynotgit.in。(使用提示:按一下圖形的任意兩個節點以取得差異。順帶一提,是否有任何 Git 網路介面提供類似的功能?)

2. SQLite 不使用 Git 的幾個原因

2.1. Git 無法提供良好的情境感知

當我想查看 SQLite 的最新動態時,我會前往 時間軸,在單一畫面中查看所有分支的最新變更摘要。只需按幾下,我就能深入查看所需的詳細資料。我甚至可以用手機這麼做。

GitHub 和 GitLab 無法提供類似的功能。我找到最接近的功能是 網路,但它的呈現速度很慢(除非已快取),提供的詳細資料遠遠不足,而且在行動裝置上幾乎無法使用。GitHub 的 提交 檢視提供了更多詳細資料,呈現速度快,而且可以在行動裝置上使用,但一次只顯示一個分支,因此我無法輕易得知是否已查看所有最近的變更。即使 GitHub/GitLab 提供了更好的介面,它們都是第三方服務。它們並非 Git 的核心部分。因此,使用它們會為專案引入另一個依賴項。

我聽說 Git 使用者通常會安裝第三方 Git 圖形檢視器,其中許多檢視器在顯示專案最近的活動上做得更好。這很好,但這些仍然是必須另外安裝和管理的第三方應用程式。許多應用程式是特定於平台的。(例如,其中一個較好的應用程式 GitUp,只適用於 Mac。)所有應用程式都要求你首先同步你的本機儲存庫,然後在你的桌面上開啟其圖形介面。即使這樣,我仍然無法在不按一下多下按鈕的情況下看到我通常想看到的內容。在辦公室外透過手機查看專案狀態並非選項。

2.2. Git 讓尋找簽入的後繼者(後代)變得困難

Git 讓你回顧過去,但無法展望未來。給定一些歷史簽入,你可以看到之前發生了什麼,但很難看到接下來發生了什麼。

相反地,Fossil 提供有用的顯示,例如 https://sqlite.dev.org.tw/src/timeline?df=major-release,以顯示衍生自最近的主要版本的全部簽入。

在 Git 中找到簽入的後代並非不可能。只是很困難。例如,有一個 stackoverflow 頁面 顯示在 unix 中尋找簽入後代的命令順序

git rev-list --all --parents | grep ".\{40\}.*.*" | awk '{print $1}'

但這不是同一件事。上述命令會提供後代清單,而不顯示分支結構,而分支結構對於了解發生了什麼很重要。而且,只有在你擁有儲存庫的本機複製時,該命令才會運作;尋找簽入的後代並非你可以透過 GitHub 或 GitLab 等網路介面執行的動作。

這不只是關於不時尋找某個簽入的後代。後代在 Fossil 中很容易取得的事實表示資訊會滲透到 Fossil 提供的網頁中。一個範例:每個 Fossil 簽入資訊頁面(範例)會顯示一個小小的「脈絡」圖,顯示該簽入的直接前代和後代。這有助於使用者維持更好的情境感知,並提供有用的功能,例如能夠在序列中按一下以跳到下一個簽入。另一個範例:Fossil 可以輕鬆顯示特定簽入周圍的脈絡(範例),這再次有助於提升情境感知,並更深入了解程式碼中發生的事情。在 Fossil 文件 中有一個 額外範例的完整頁面

理論上,只要有正確的擴充套件和工具,並使用正確的指令,Git 也可以做到上述所有事情。但這不容易做到,因此很少人會這麼做。因此,開發人員較不了解程式碼中發生的事情。

2.3. Git 的心智模式不必要地複雜

Git 的複雜性會分散對正在開發軟體的注意力。Git 使用者需要記住所有下列事項

  1. 工作目錄
  2. 「索引」或暫存區
  3. 本機端主控點
  4. 遠端端主控點的本機端副本
  5. 實際的遠端端主控點

Git 有指令(和/或指令選項)可用於在所有這些位置之間移動和比較內容。

相較之下,Fossil 使用者只需要考慮自己的工作目錄和他們正在處理的簽入。這減少了 60% 的分心。每個開發人員都有有限的腦力循環。Fossil 需要較少的腦力循環來操作,因此可以釋放智力資源來專注於正在開發的軟體。

一位同時使用 Git 和 Fossil 的使用者 在 HN 寫道

Fossil 讓我覺得安心,因為我可以使用單一指令將所有內容...同步到伺服器....使用 git 時我從來沒有這種安心感。

2.4. Git 沒有追蹤歷史分支名稱

Git 保留了簽入順序的完整 DAG。但是,分支標籤是本機資訊,在分支關閉後不會同步也不會保留。這使得檢閱歷史分支變得繁瑣。

舉例來說,假設一位客戶問你:「兩年前的『prefer-coroutine-sort-subquery』分支後來怎麼了?」你可以試著查看版本控制系統中的歷史記錄來回答,如下所示

Fossil 視圖清楚地顯示該分支最終合併回主幹。它顯示分支的開始位置,並顯示主幹上的變更合併到分支的兩個場合。GitHub 沒有顯示任何這些資訊。事實上,GitHub 顯示在嘗試找出發生了什麼事時幾乎沒有用。

許多讀者推薦了各種第三方 Git GUI,這些 GUI 在顯示歷史開發活動方面做得更好。也許其中一些確實比原生 Git 和/或 GitHub 更好,儘管它們都受到 Git 在同步時不保留歷史分支名稱的事實所阻礙。即使那些其他工具更好,但必須使用第三方工具才能取得所需資訊的事實並不能說明核心系統的好壞。

2.5. Git 需要更多管理支援

Git 是複雜的軟體。需要某種安裝程式才能將 Git 放置在開發人員工作站上,或升級到更新版本的 Git。建立 Git 伺服器並非易事,因此大多數開發人員使用 GitHub 或 GitLab 等第三方服務,從而引入了額外的依賴關係。

相較之下,Fossil 是單一的獨立二進位檔,安裝時只要將它放在 $PATH 中即可。這個二進位檔包含了 Git 核心、GitHub 和/或 GitLab 的所有功能。它管理著包含 wiki、錯誤追蹤和論壇的社群伺服器,提供給消費者的封裝下載、登入管理等,且不需要額外的軟體。建立 Fossil 的社群伺服器只需要幾分鐘。而且 Fossil 很有效率。Fossil 伺服器可以在每月 5 美元的 VPS 或 Raspberry Pi 上順利執行,而 GitLab 和類似的軟體則需要更強大的硬體。

較少的管理工作表示程式設計師可以花更多時間在軟體(此例中為 SQLite)的開發上,而花較少時間在版本控制系統上。

2.6. Git 提供了糟糕的使用者體驗

以下的 https://xkcd.com/1597/ 漫畫雖然誇張,但卻很貼近事實

讓我們面對現實吧。很少有人會爭論 Git 提供了次佳的使用者體驗。許多底層的實作都顯示在使用者介面上。介面很糟糕,甚至有一個惡搞網站可以產生 假的 git 手冊頁面

設計軟體很困難。這需要大量的專注。一個好的版本控制系統應該提供開發人員協助,而不是挫折。Git 在這方面在過去十年中已經有所改善,但它還有很長的路要走。

3. Git 使用者指南,用於存取 SQLite 原始碼

如果您是忠實的 Git 使用者,您仍然可以輕鬆存取 SQLite。本節提供了一些關於如何這樣做的提示。

3.1. 官方 GitHub 鏡像

截至 2019-03-20,GitHub 上現在有一個 SQLite 原始碼的 官方 Git 鏡像

該鏡像是 SQLite 的 正規 Fossil 儲存庫 的增量匯出。一個 cron 作業每小時更新一次 GitHub 儲存庫。這是一個單向的唯讀程式碼鏡像。不接受透過 GitHub 提出拉取請求或變更。GitHub 儲存庫僅複製 Fossil 儲存庫中的內容。所有變更都透過 Fossil 輸入。

Git 鏡像上識別簽入和檔案的雜湊與 Fossil 中的雜湊不同。造成這種情況的原因有很多,其中最主要的原因是 Fossil 使用 SHA3-256 雜湊,而 Git 使用 SHA1 雜湊。在匯出期間,每個簽入的原始 Fossil 雜湊會新增為簽入註解的頁尾。為避免混淆,在參考 SQLite 簽入時,請務必使用原始 Fossil 雜湊,而不是 Git 雜湊。

3.2. 網路存取

SQLite Fossil 儲存庫 包含連結,可供下載任何歷史版本的 SQLite 的 Tarball、ZIP 檔案或 SQLite 檔案。這些下載的網址很簡單,可以輕鬆整合到自動化工具中。格式為

https://sqlite.dev.org.tw/src/tarball/VERSION/sqlite.tar.gz

只要將 VERSION 替換為要下載的版本的說明即可。VERSION 可以是特定簽入的加密雜湊名稱的前綴,或分支的名稱(這種情況下,會擷取分支的最新版本),或特定簽入的標籤,例如「version-3.23.1」

https://sqlite.dev.org.tw/src/tarball/version-3.23.1/sqlite.tar.gz

若要取得最新版本,請將 VERSION 設定為「release」,如下所示

https://sqlite.dev.org.tw/src/tarball/release/sqlite.tar.gz

若要取得最新的 trunk 簽入,請將 VERSION 設定為「trunk」

https://sqlite.dev.org.tw/src/tarball/trunk/sqlite.tar.gz

以此類推。對於 ZIP 檔案和 SQLite 檔案,只需將「/tarball/」元素變更為「/zip/」或「/sqlar/」,並可能變更下載檔案的名稱,加上「.zip」或「.sqlar」字尾。

3.3. Fossil 存取

Fossil 安裝和使用很簡單。以下是 unix 的步驟。(Windows 類似。)

  1. https://fossil-scm.org/fossil/uv/download.html 下載獨立的 Fossil 可執行檔,並將可執行檔放在 $PATH 的某個位置。
  2. mkdir ~/fossils
  3. fossil clone https://sqlite.dev.org.tw/src ~/fossils/sqlite.fossil
  4. mkdir ~/sqlite; cd ~/sqlite
  5. fossil open ~/fossils/sqlite.fossil

此時,您已準備好輸入「./configure; make」(或在具有 MSVC 的 Windows 上輸入「nmake /f Makefile.msc」)。

若要將您的結帳變更為 Fossil 的不同版本,請使用「update」指令

fossil update 版本

使用「trunk」作為 版本,以取得 SQLite 的最新 trunk 版本。或使用加密雜湊名稱的前綴,或某個分支或標籤的名稱。請參閱 https://fossil-scm.org/fossil/doc/trunk/www/checkin_names.wiki,以取得更多建議,了解哪些名稱可作為 版本 使用。

從 ~/sqlite 結帳中使用「fossil ui」指令,以開啟網站的本地副本。

可在 https://fossil-scm.org/fossil/doc/trunk/www/permutedindex.html 找到 Fossil 的其他文件。

不要害怕探索和實驗。未登入時,您將無法回推所做的任何變更,因此您不會損壞專案。

3.4. 驗證原始碼完整性

如果您需要驗證您擁有的 SQLite 原始碼是真實的,且未被以任何方式修改(可能是由對手),可以使用幾個簡單的命令列工具來完成。在 SQLite 原始碼樹的根目錄中有一個名為「manifest」的檔案。manifest 檔案包含原始碼樹中每個其他檔案的名稱,以及該檔案的 SHA1 或 SHA3-256 hash。(SHA1 用於較舊的檔案,SHA3-256 用於較新的檔案。)您可以撰寫一個腳本來萃取這些 hash,並針對原始碼檔案驗證它們。簽入的 hash 名稱只是「manifest」檔案本身的 SHA3-256 hash,如果最後一行以「# Remove this line...」開頭,則最後一行可能會省略。

4. 另請參閱

討論 Fossil 和 Git 的其他頁面包括

此頁面最後修改於 2023-02-27 02:07:35 UTC