Git 的歷史:從 BitKeeper 決裂到 GitHub 與 GitLab
2005 年 Linux 核心失去 BitKeeper 的免費授權,Git 因此誕生。依第一個 commit 與郵件論壇原文,整理設計目標、交棒 Junio Hamano、1.0 版,以及 GitHub 與 GitLab 如何讓它成為預設工具,並說明如何在自己的 VPS 上用 Git 部署與備份。
Git 的歷史,先說結論
Git 的歷史從一次授權破裂開始:2005 年,Linux 核心團隊失去了 BitKeeper 的免費使用權,Linus Torvalds 於是自己寫了一套版本控制工具。git.git 儲存庫的第一個 commit 日期是 2005 年 4 月 7 日。同年 7 月底,他把維護者的位置交給 Junio C Hamano。12 月 21 日,Hamano 標記了 1.0.0 版。後來 GitHub 與 GitLab 把這個原本為核心開發而寫的工具,變成幾乎所有軟體團隊的預設選擇。
以下內容以一手資料為準:git.git 裡的 commit 與 tag、Linux 核心郵件論壇(LKML,Linux Kernel Mailing List)的存檔、Git 專案自己的 Pro Git 書,以及當事人的訪談。找不到一手來源的日期,這裡就不寫。Torvalds 本人的生平不在這裡重複,這篇只講 Git 這個工具本身。
2002 年以前:patch 和壓縮檔
Git 官方網站上的 Pro Git 書寫道,1991 到 2002 年間,核心的修改是以 patch 和封存檔(archived files)的形式傳來傳去。patch 是一份文字檔,記錄兩個版本之間刪掉了哪些行、加入了哪些行。維護者收到 patch,套用到自己手上的原始碼,再把結果打包成壓縮檔發布。
這種做法沒有一個工具替你記錄完整的歷史。哪個修改套用在哪個版本上,要靠郵件和人的記憶。Pro Git 對這段時期只寫了這一句。我們也找不到 kernel.org 或 LKML 上描述當年流程細節的一手頁面,所以不再補充細節。核心本身在這些年怎麼長大,可以看Linux 核心歷史時間軸。
2002 年:核心為什麼改用專有的 BitKeeper
Pro Git 的說法是:2002 年,核心專案開始使用專有的分散式版本控制系統(DVCS,distributed version control system)BitKeeper。LKML 上一份 2002 年 2 月 6 日的 2.5 版狀態報告,作者是 Guillaume Boissiere,裡面寫著 "Equally exciting is Linus' new use of BitKeeper." 所以最晚在 2002 年 2 月,Torvalds 已經在用它。他在 2025 年的訪談中也說,自己從 2002 年用到 2005 年。
「分散式」的意思是:每個開發者手上都有完整的歷史,不需要連到一台中央伺服器才能提交。Torvalds 在 2005 年 4 月 7 日的一封郵件中解釋過這件事對他的價值。BitKeeper 讓他可以直接從各個維護者那裡「拉」(pull)修改,所以還沒處理的工作不會全部堆在他一個人身上。
代價在授權上。BitKeeper 不是開源軟體,核心社群能免費使用它,是因為開發它的公司 BitMover 願意提供。Torvalds 在 2025 年接受 GitLab 的 Patrick Steinhardt 訪談時說得很直接:"But the biggest problem with BK was the licensing"。一個開源核心的日常開發流程,依賴一家公司決定要不要繼續免費提供的工具。這就是當年爭議的核心。開源社群為什麼這麼在意授權,開源軟體的歷史有更完整的背景。
2005 年:BitKeeper 的免費授權為什麼被收回
Pro Git 的記載是:2005 年,開發 Linux 核心的社群與開發 BitKeeper 的商業公司關係破裂,這個工具的免費地位被撤銷。它沒有寫日期,也沒有寫原因的細節。
LKML 存檔裡,Torvalds 的〈Kernel SCM saga..〉時間戳記是 2005 年 4 月 6 日(存檔以 EST 美東時間標示)。SCM 是 source code management,原始碼管理。他在信中說,核心團隊花了一兩個月想解決 BitKeeper 使用上的衝突,但沒有成功,所以他開始找替代方案。BitKeeper 並沒有馬上被丟掉,他停用它,主要是為了讓大家有時間找出替代方案。同一封信裡,他請大家不要怪 BitMover 和 Larry McVoy,也說 BitKeeper 改善了核心開發的方式。在替代方案裡,他認為 monotone 最可行,並請大家不要再向開發者推銷 Subversion。原文可以在 lkml.iu.edu 的存檔讀到。
McVoy 與 Tridgell 兩方的說法
多數報導把這次破裂和 Andrew Tridgell 寫的一個 BitKeeper 相容用戶端連在一起。我們能打開、能查證的一手紀錄只有這一筆:SourceForge 上的 SourcePuller 專案由使用者 tridge 在 2005 年 4 月 21 日登記,專案描述是 "sp is a source code management client interoperable with BitKeeper"。登記日期是專案頁面建立的日期,不等於開始寫程式的日期,也晚於 4 月 6 日那封信。
Larry McVoy 與 Andrew Tridgell 各自怎麼描述這件事,我們找不到可以直接打開的一手聲明,所以這裡不轉述任何一方的說法,也不替任何一方下結論。想自己判斷的讀者,可以從上面那封 LKML 郵件開始,沿著 2005 年 4 月的討論串往下讀。
Torvalds 想要什麼樣的工具:Git 的設計目標
Git 的設計目標,最早的線索在 2005 年 4 月 7 日那封回覆裡。Torvalds 說,用郵件寄 patch 只能當作暫時的做法,長期無法擴展,因為 patch 一封一封套用很花時間,一長串郵件可能要處理好幾個小時。他寫道,一個以 patch 為基礎的 SCM "would need to be _faster_ than BK is",又說 "latency is critical"。latency 指的是等待時間:每套用一個 patch 要等多久。
同一封信也看得出他對架構的偏好。他不喜歡集中式的模型。他說如果真的不得已,可以在一個可信任的網站上架 SVN,只讓少數人提交,但他擔心這種做法一旦開始,以後會很難擺脫。
資料完整性是第二條線索,而它最清楚地寫在程式碼裡。第一個 commit 的 README 這樣描述物件資料庫:
The object database is literally just a content-addressable collection of objects. All objects are named by their content, which is approximated by the SHA1 hash of the object itself.
「內容定址」(content-addressable)的意思是:每個物件的名字就是它內容的 SHA1 雜湊值。內容只要被改掉一個位元,算出來的雜湊就對不上它的名字,所以損壞或竄改會被發現。這也是 git fsck 能檢查整個儲存庫的原因。要注意的是,README 說的是 2005 年 4 月初版的做法,今天 Git 怎麼計算物件雜湊,要看現在的文件。
20 年後,Torvalds 在 GitLab 於 2025 年 4 月 7 日發表的訪談中回顧,主要目標是 "to be distributed and high performance",並且要 "be something you could absolutely rely on to catch any corruption." 這是事後的回顧,不是 2005 年郵件論壇上的原話。我們打開的那幾封 2005 年郵件沒有提到完整性或雜湊,所以完整性這個目標,最早的一手證據是上面的 README。
Git 專案自己的 Pro Git 書,後來把新系統的目標整理成這份清單:
- 速度(Speed)
- 簡單的設計(Simple design)
- 對非線性開發的強力支援,也就是同時有數千個平行分支
- 完全分散式(Fully distributed)
- 能有效率地處理像 Linux 核心這樣的大型專案,包括速度和資料量
這份清單是專案後來的整理,不是 Torvalds 在 2005 年的原話。
第一個 commit:2005 年 4 月 7 日
git.git 的第一個 commit 是 e83c5163316f89bfbde7d9ab23ca2e25604af290,作者是 Linus Torvalds。它是一個根 commit(root commit),也就是沒有任何父 commit。作者與提交日期都是 Thu Apr 07 15:13:13 2005 -0700,換算成 UTC 是 2005 年 4 月 7 日 22:13:13。換算成台灣或香港時間(UTC+8),已經是 4 月 8 日早上 6 點 13 分。所以如果你在中文資料看到「4 月 8 日」,差別來自時區,不是資料錯誤。
這個 commit 加入了 11 個檔案、1,244 行。commit 訊息是 Initial revision of "git", the information manager from hell。README 的標題寫著 GIT - the stupid content tracker,並把它形容為 "a stupid (but extremely fast) directory content manager"。
你可以在任何一台裝了 Git 的機器上親眼看到它。先安裝 Git,再複製 git.git 的鏡像:
sudo apt update && sudo apt install -y git
git clone https://github.com/git/git.git
cd git
git show --stat e83c5163316f89bfbde7d9ab23ca2e25604af290輸出的 Date: 那一行應該是 Thu Apr 7 15:13:13 2005 -0700,最後一行應該顯示 11 個檔案、1244 行新增。複製的資料量不小,在小型 VPS 上要等一下。要確認它真的沒有父 commit,看它的原始物件:
git cat-file -p e83c5163316f89bfbde7d9ab23ca2e25604af290一般的 commit 物件會有一行 parent,指向上一個 commit。這個物件只有 tree、author、committer 和訊息,沒有 parent 行,因為它前面什麼都沒有。
交棒給 Junio C Hamano:2005 年 7 月
Git 的維護者從 2005 年夏天起就不是 Torvalds。Hamano 在 GitHub 2020 年的訪談中說,他 "probably got involved about a week after Linus announced",一直到 Torvalds "gave the maintainer role to me at the end of July 2005"。
Torvalds 那邊的紀錄是一封寄到 git 郵件論壇、標題為〈Meet the new maintainer..〉的信,LWN 轉載的郵件標頭日期是 2005 年 7 月 26 日(美國太平洋時間)。他在信中說,kernel.org 上這個專案的「owner」欄位已經改成 Junio,Junio 是理所當然的人選,而他自己之後會像其他貢獻者一樣,把 patch 寄給 Junio。
從第一個 commit 到交棒,不到四個月。Torvalds 在 2025 年的訪談中說 "I did Git because I had to.",也說 "it really is Junio who has led the project"。很多人以為 Git 一直是 Torvalds 的專案。實際上,今天大家用的 Git,大部分歲月是在 Hamano 手上長成的。
Git 1.0.0:2005 年 12 月 21 日
git.git 裡的 v1.0.0 tag 由 Hamano 標記,日期是 Wed Dec 21 00:01:00 2005 -0800,tag 訊息就是 GIT 1.0.0。公告信〈[ANNOUNCE] GIT 1.0.0〉的日期是同一天的 00:00:10 -0800。兩個時間換成 UTC,都是 12 月 21 日早上 8 點左右。
公告本身很低調。Hamano 寫道,"1.0.0" 這個名字理應代表一個重大里程碑,但其實並不是。他也說,1.0 之前的版本已經被核心開發者在實際工作中用了好一段時間。換句話說,Git 先被拿來用,版本號後來才補上。連 1.0.0 的文件 Documentation/git.txt 都還寫著 git - the stupid content tracker。
在你剛才複製的 git.git 裡,可以直接看這個 tag:
git show --no-patch v1.0.0輸出會先列出 tagger 與日期,接著是 GIT 1.0.0 這行訊息,再來是它指向的 commit c2f3bf071ee90b01f2d629921bb04c4f798f02fa。
BitKeeper 後來怎麼了
BitKeeper 在 2016 年 5 月開源。它的使用者論壇上有一篇〈Bk-7.2ce released 2016-05-09〉,寫著 "This is the first open source release of BitKeeper. Many changes involve removing the licensing code." 也就是說,開源版本做的一大部分工作,是拿掉授權檢查的程式碼。bitkeeper.org 現在寫著它以 Apache 2.0 授權開源,網站上提供的版本是 7.3.3。
當年讓核心社群離開的原因是授權,而 11 年後它自己拿掉了授權程式碼。不過那時 Git 早已是預設工具了。
GitHub 與 GitLab:核心工具怎麼變成大家的預設
Git 本身沒有「中央伺服器」的概念。每一份複製都是完整的儲存庫。這對核心開發很合適,但對一個只想分享程式碼的小團隊來說,總得有一個大家都能推(push)上去的地方,還要有一個能在瀏覽器裡看程式碼的頁面。GitHub 和 GitLab 補上的就是這一塊。
GitHub 在 2008 年 10 月 19 日的部落格文章〈GitHub turns one〉裡寫道 "just one year ago today we made the first commit to the GitHub repository",並說剛剛超過 2 萬個公開儲存庫。正式對外開放的日期,GitHub 自己的部落格也還留著:2008 年 4 月 10 日的〈We Launched〉寫著 "GitHub is officially live. Thanks for the awesome beta everyone.",也就是在這一天結束 beta、正式上線。GitHub 是一個服務,不是 Git 本身。兩者的分工,Git、GitHub 和自架 Git 伺服器的差別講得很清楚。
GitLab 走的是另一條路。共同創辦人 Dmitriy Zaporozhets 說,他在 2011 年 10 月開始這個專案,當時 "There was no modern open source software to run on your server.",於是他把它當成一個業餘專案(hobby project)來做。後來他與 Sytse Sijbrandij 成立了荷蘭公司 GitLab B.V.,公司之後改以美國的 GitLab, Inc. 營運。重點是 GitLab 從一開始就是可以裝在你自己伺服器上的軟體,這讓「自己擁有儲存庫」成為一個實際的選項。
對租 VPS 的人來說,Git 的歷史有什麼用
Git 是為了「不依賴任何一家公司的工具」而誕生的。這個出身今天仍然直接影響你:程式碼放在哪裡,可以由你自己決定。在一台 VPS 上,Git 可以同時是部署工具和備份工具。
用 Git 推送部署
在伺服器上建立一個 bare 儲存庫。bare 指的是只有 Git 資料、沒有工作目錄的儲存庫,它專門用來接收 push:
sudo mkdir -p /srv/git /srv/app
sudo chown "$USER" /srv/git /srv/app
git init --bare --initial-branch=main /srv/git/app.git接著加一個 post-receive hook。每次有人 push 成功,Git 就會執行它,把 main 分支的檔案取出到 /srv/app:
cat > /srv/git/app.git/hooks/post-receive <<'EOF'
#!/bin/sh
git --work-tree=/srv/app --git-dir=/srv/git/app.git checkout -f main
EOF
chmod +x /srv/git/app.git/hooks/post-receive在你自己的電腦上,把這台 VPS 加為遠端,然後推送:
git remote add vps ssh://you@vps.example.com/srv/git/app.git
git push vps main推送完成後,在伺服器上執行 ls /srv/app,應該會看到你專案的檔案。如果 /srv/app 是空的,先用 ls -l /srv/git/app.git/hooks/post-receive 確認權限裡有 x。hook 檔案沒有執行權限時,Git 不會執行它,所以 push 成功了,檔案卻沒有更新。
為什麼一定要用 bare 儲存庫?如果你直接 push 到一個普通儲存庫目前所在的分支,Git 會拒絕,你會看到:
! [remote rejected] main -> main (branch is currently checked out)Git 拒絕的原因是:更新目前檢出的分支,會讓那個工作目錄裡的檔案和分支內容不一致。bare 儲存庫沒有工作目錄,所以沒有這個問題。
用 Git 備份託管平台上的儲存庫
就算你的程式碼放在 GitHub,也可以在 VPS 上留一份完整的鏡像:
git clone --mirror https://github.com/your-name/app.git /srv/git/app-mirror.git
git -C /srv/git/app-mirror.git remote update --prune--mirror 會複製所有分支與 tag。第二行用來定期更新,可以放進 cron 或 systemd timer。--prune 會把上游已經刪掉的分支也刪掉,所以如果你想保留被刪掉的分支,就不要加它。要注意,鏡像只包含 Git 資料。GitHub 上 issue 和 pull request 的討論內容不在 Git 裡,不會被備份到。
想把同一個專案同時推到 GitHub 和自己的伺服器,可以看同時推送到 GitHub 與自架 Git 伺服器。如果你需要網頁介面和權限管理,可以比較自架 Git 伺服器的幾種選擇,從單純的 SSH 到完整的 GitLab 都有。
FAQ
Git 的第一個 commit 是什麼時候?
git.git 的第一個 commit 是 e83c5163316f89bfbde7d9ab23ca2e25604af290,作者是 Linus Torvalds,日期是 Thu Apr 07 15:13:13 2005 -0700,也就是 UTC 的 2005 年 4 月 7 日 22:13。換成台灣或香港時間已經是 4 月 8 日早上,所以有些中文資料寫 4 月 8 日。複製 git.git 之後執行 git show --stat e83c5163316f89bfbde7d9ab23ca2e25604af290 就能親眼看到。
Linux 核心為什麼不再使用 BitKeeper?
BitKeeper 是專有軟體,核心社群能免費使用它,是因為 BitMover 願意提供。Git 官方的 Pro Git 書記載,2005 年雙方關係破裂,BitKeeper 的免費地位被撤銷。Torvalds 在 2005 年 4 月 6 日的〈Kernel SCM saga..〉郵件裡說,大家花了一兩個月想解決使用上的衝突但沒有成功,並請大家不要怪 BitMover。他在 2025 年的訪談中說,BitKeeper 最大的問題是授權。
現在是誰在維護 Git?
Junio C Hamano。Torvalds 在 2005 年 7 月底把維護者角色交給他,Hamano 自己在 GitHub 2020 年的訪談中也這樣說。Torvalds 在 2025 年的訪談中說,真正帶領這個專案的是 Junio。Git 1.0.0 的 tag 也是由 Hamano 在 2005 年 12 月 21 日標記的。
Git 和 GitHub 是同一個東西嗎?
不是。Git 是一個版本控制程式,任何電腦上都能執行,不需要連到任何服務。GitHub 是一個託管 Git 儲存庫的網站,它在 2008 年的部落格文章裡說自己的第一個 commit 是在一年前。你可以只用 Git,把儲存庫放在自己的 VPS 上,用 git init --bare 建立,再用 SSH 推送。
在自己的 VPS 上放 Git 儲存庫需要什麼?
只需要 Git 和 SSH。在伺服器上執行 git init --bare --initial-branch=main /srv/git/app.git,在自己的電腦上用 git remote add 加入 ssh:// 位址,再執行 git push。需要網頁介面或帳號權限時,再考慮 Forgejo 或自架的 GitLab 這類軟體。