博客 / 詳情

返回

【5分鐘學一個新技能】Git:改變世界的協作革命

剛學編程那陣子,我最怕兩件事:一是代碼寫不出來,二是代碼寫出來卻弄丟了。

辛辛苦苦改了一晚上代碼,原本能跑,更新後如果出了問題就難以回滾亦或是修復,只能盯着空白髮呆;

和別人一起開發項目,QQ互傳壓縮包,有時也不知道對方改了哪裏,遇到報錯更是頭暈,只能對七八個版本傻眼——到底哪個能用?

調侃之餘,有羣友説:“你們該用版本管理。”

那是我第一次聽説這個詞。

什麼是版本管理?

簡單説,版本管理就是給你的代碼“拍照片”。

想象一下你寫文檔。寫完一稿,存成“報告v1.docx”。改了點,存成“報告v2.docx”。又改了點,存成“報告最終版.docx”。再改,變成“報告真的最終版.docx”。

這就是最原始的版本管理——手動命名,手動備份。問題很明顯:版本多了就亂,想找回某個中間版本得一個個打開看。

專業的版本管理系統,就是幫你自動化這個過程的工具。它會:

  1. 記錄每次改動的內容
  2. 記錄誰在什麼時候改的
  3. 記錄為什麼要改
  4. 讓你隨時回到任意歷史版本

在Git出現前,已經有CVS、Subversion這樣的版本控制工具。但它們都有個共同問題:必須連接中央服務器。這就像在圖書館借書——書只有一本,你得登記誰借走了,別人得等着。

Linus的“十日革命”

2005年,Linux內核開發團隊就面臨這樣的困境。他們用的BitKeeper突然要收費,而現有的開源工具又滿足不了需求。

Linux之父Linus Torvalds後來在採訪中説:“當時的情況是,要麼我們繼續用不合適的工具,要麼我自己造一個合適的。”他選擇了後者。

4月3日,Linus開始寫Git。他在設計文檔裏寫了三個目標:

  1. 速度要比其他工具快十倍
  2. 完全分佈式,不需要中央服務器
  3. 能處理像Linux內核這樣的大項目

十天後,Git第一個版本發佈。4月16日,Linus用Git管理Linux內核源碼。4月20日,他宣佈Git已經能自我託管——用Git來管理Git自己的代碼。

早期的Git很難用。命令複雜,概念抽象。有開發者抱怨:“這玩意兒比Linux內核還難懂。”Linus的回覆很直接:“不爽不要用。”

但Git有兩個設計太超前了:

第一,分佈式架構。每個人的電腦上都有完整的倉庫歷史,不需要聯網也能提交代碼。這就像每個人都有一本完整的圖書館目錄,不需要去總館查資料。

第二,分支管理。分支是同時控制不同版本代碼的絕佳工具。例如,你希望在穩定版代碼的基礎上加點新功能,就可以基於主分支創建新分支,在新分支上隨意更改,這讓“嘗試性開發”成為可能——想到什麼點子,開個分支試試,不行就刪掉。

GitHub:讓Git飛入尋常百姓家

Git很強,但直到2008年,它主要還是極客在用。直到三個年輕人創立了GitHub。

GitHub做了件簡單但革命性的事:給Git套了個網頁界面。

突然之間,事情變得直觀了。代碼倉庫變成網頁,提交歷史變成時間軸,分支合併變成可視化操作。更重要的是,他們創造了Pull Request(PR,拉取請求)。這是GitHub最偉大的創新。你不再需要郵件發送補丁,而是:

  1. Fork(複製)別人的倉庫
  2. 在自己的副本上修改
  3. 發起Pull Request,請求原作者合併你的修改
  4. 在PR中進行代碼審查、討論

這種模式極大地降低了開源貢獻的門檻。2015年,微軟將.NET框架開源並放到GitHub上時,社區震驚了。這個曾經視開源為敵的公司,現在主動擁抱開源。

我清楚地記得第一次在GitHub上提交PR的場景。那是個朋友的開源小項目,我發現文檔內容有誤。點了“Fork”按鈕,把項目複製到我的賬户。修改,提交,然後發起PR。項目維護者看到了,點了個“Merge”。兩分鐘後,我的修改成了項目的一部分。

那種感覺很難形容——好像突然之間,我也能為那些遙不可及的大項目做貢獻了。

GitHub火了。到2012年,它已經有超過200萬個倉庫。Ruby on Rails、jQuery、Node.js這些知名項目都搬了上去。微軟也把.NET框架開源放到了GitHub,這在以前是不可想象的。

GitHub的成功引來了競爭者。2011年,GitLab誕生。它的賣點是“可以自己部署”。企業可以把GitLab裝在自己的服務器上,代碼不出內網。除了代碼託管,它還集成了:

  • CI/CD流水線:自動測試、構建、部署
  • 問題追蹤:bug報告、功能請求
  • Wiki:項目文檔
  • 代碼質量分析:自動化代碼檢查

中國這邊,2013年出現了Gitee(碼雲)。起初很多人覺得“是山寨GitHub”,但後來發現了它的價值:國內訪問快,符合中國法規,還有中文界面。

不只是代碼

Git的影響遠遠超出了編程世界。

  • 學術研究:學者用Git管理論文草稿,每次修改都有記錄
  • 法律文件:律師事務所用類似Git的系統管理合同版本
  • 圖書出版:出版社用Git協調作者、編輯、校對的工作
  • 政府文檔:有些政府部門用Git追蹤政策文件的修訂

實際怎麼用?

第一步:初始化與配置

先安裝Git,安裝步驟略。


開始前,先告訴Git你是誰:

git config --global user.name ”你的名字“
git config --global user.email ”你的郵箱“

這很重要,因為Git的所有提交都會記錄作者信息。


創建一個新倉庫:

mkdir my-project # 新建一個名為“my-project”的文件夾
cd my-project # 進入該文件夾
git init # Git倉庫初始化

執行git init後,當前目錄會出現一個隱藏的.git文件夾。這就是Git的“大腦”,裏面存儲着所有的版本信息、配置和索引。

或者,你也可以直接下載雲端倉庫:

git clone https://github.com/username/repo.git # 此處鏈接為你倉庫的實際在線鏈接,clone就是“克隆”的意思,會把倉庫下載到當前目錄下
cd repo # 進入倉庫文件夾,文件夾名稱為倉庫名

查看倉庫狀態:

git status

這是你最常用的命令之一。它會告訴你:

  • 哪些文件被修改了但還沒暫存(紅色)
  • 哪些文件已經暫存等待提交(綠色)
  • 是否有未跟蹤的新文件

第二步:基礎工作流

假設你寫了一個簡單的Python腳本:

# hello.py
print(”Hello, World!“)

把文件添加到暫存區:

git add hello.py # add後為你的實際文件名

或者添加所有修改:

git add . # .表示所有文件

暫存區(Staging Area)是Git的精妙設計。它就像購物車——你可以把多個改動放進去,最後一次性結賬。這讓你可以精心組織每次提交的內容。


正式提交:

git commit -m ”添加hello.py腳本“

每次提交都應該有一個清晰的描述。好的提交信息應該像新聞標題:簡明扼要地説明做了什麼。比如:

  • ❌ 錯誤:”修復bug“、”更新代碼“
  • ✅ 正確:”修復用户登錄時的空指針異常“、”添加用户頭像上傳功能“

目前業界公認度最高的提交信息標準是 Conventional Commits(約定式提交)。它最初源於 Angular 團隊的規範,現在已成為許多開源項目(如 Vue、React、Babel 等)和大型團隊的通用標準。

1. 核心格式

遵循<type>(<scope>): <description>的結構,例如:

  • feat(auth): add OAuth2 login flow
  • fix(ui): correct button alignment on dashboard

2. 關鍵規則

  • 類型 (Type):必須使用特定關鍵詞,如 feat(新功能)、fix(修復)、docs(文檔)、style(格式)、refactor(重構)、test(測試)、chore(構建/工具)等。
  • 時態:使用現在時(如 ”add“ 而非 ”added“),且首字母不大寫
  • 長度:標題行建議不超過 50 字符,正文行建議不超過 72 字符。
  • 空行:標題與正文之間必須有一個空行。

3. 為什麼用這個標準?

  • 自動化工具:能自動生成 CHANGELOG(更新日誌)。
  • 語義化版本:能根據 feat 和 fix 自動決定版本號升級(如 1.0.0 → 1.1.0)。
  • 可讀性:讓代碼歷史像一本清晰的説明書,便於團隊協作。

查看提交歷史:

git log

默認顯示完整的提交信息。如果想要簡潔視圖:

git log --oneline --graph --all

這會顯示一個可視化的分支圖,特別適合查看複雜的分支結構。


第三步:撤銷與回滾

寫代碼難免犯錯,Git提供了多種“後悔藥”。

場景1:還沒暫存就發現寫錯了

# 放棄某個文件的修改
git checkout -- hello.py

# 放棄所有修改(危險!請確認你真的不需要這些修改)
git checkout -- .

場景2:已經暫存但想撤銷

# 把文件從暫存區移出,但保留修改
git reset HEAD hello.py

# 然後可以用checkout放棄修改
git checkout -- hello.py

場景3:已經提交但想撤銷

# 查看提交歷史,找到要回退的版本
git log --oneline

# 假設我們看到:
# a1b2c3d 添加新功能
# e4f5g6h 修復bug
# i7j8k9l 初始提交

# 回到修復bug的那個版本
git reset --hard e4f5g6h

--hard參數會徹底丟棄之後的提交,慎用!如果你只是想撤銷某個提交但保留更改:

git revert e4f5g6h

這會創建一個新的提交來撤銷指定提交的修改,更安全。


第四步:分支管理

分支是Git最強大的功能之一。它讓你可以:

  • 同時開發多個功能
  • 安全地實驗新想法
  • 隔離bug修復和功能開發

創建並切換到新分支:

git checkout -b new-feature

這等價於:

git branch new-feature    # 創建分支
git checkout new-feature  # 切換分支

在新分支上開發完成後,切換回主分支併合並:

git checkout main
git merge new-feature

如果合併順利,Git會執行“快進合併”(Fast-forward)。如果有衝突,Git會提示你解決。


刪除已合併的分支:

git branch -d new-feature

強制刪除未合併的分支:

git branch -D experimental

查看所有分支:

git branch     # 本地分支
git branch -r  # 遠程分支
git branch -a  # 所有分支

第五步:遠程協作

本地Git再強大,也需要與團隊協作。這就是遠程倉庫的用武之地。


添加遠程倉庫:

git remote add origin https://github.com/username/repo.git

origin是遠程倉庫的默認別名,你可以用其他名字。


查看遠程倉庫:

git remote -v

推送本地提交到遠程:

git push origin main

第一次推送時可能需要指定上游分支:

git push -u origin main

-u參數設置上游關聯,之後可以直接用git push


拉取遠程更新:

git pull origin main

這等價於:

git fetch origin   # 下載遠程更新
git merge origin/main  # 合併到當前分支

有時候你只想查看遠程有什麼更新,而不想立即合併:

git fetch origin
git log origin/main --oneline  # 查看遠程分支的提交

第六步:處理衝突

衝突是團隊協作的必經之路。當兩個人修改了同一文件的同一區域時,Git無法自動合併,需要人工解決。

發生衝突時,Git會在文件中標記衝突:

<<<<<<< HEAD
print(”Hello from Alice!“)
=======
print(”Hello from Bob!“)
>>>>>>> feature-branch

你需要:

  1. 編輯文件,選擇保留哪部分(或都保留)
  2. 刪除衝突標記(<<<<<<<=======>>>>>>>
  3. 添加解決後的文件:git add filename
  4. 完成合並:git commit

查看合併狀態:

git merge --abort  # 取消合併,回到合併前狀態
git status         # 查看當前衝突文件

第七步:高級技巧

儲藏更改(Stashing):

當你需要切換分支但當前工作還沒完成時:

git stash          # 儲藏當前修改
git stash list     # 查看儲藏列表
git stash pop      # 應用最新的儲藏並刪除
git stash apply    # 應用儲藏但不刪除

查看差異

git diff                    # 工作區與暫存區的差異
git diff --staged          # 暫存區與最新提交的差異
git diff commit1 commit2   # 兩個提交之間的差異

重寫歷史(謹慎使用!):

修改最後一次提交:
git commit --amend
交互式變基(修改多個提交):
git rebase -i HEAD~3  # 修改最近3個提交

子模塊(Submodules):

用於在項目中包含其他Git倉庫:

git submodule add https://github.com/other/repo.git
git submodule update --init --recursive

實際工作流示例

讓我分享一個真實的工作流。假設我們要開發一個新功能:

  1. 從最新代碼開始
git checkout main
git pull origin main
  1. 創建功能分支
git checkout -b feature/user-profile   
  1. 開發、測試、提交
# 多次小提交,而不是一次大提交
git add user/profile.py
git commit -m ”添加用户基本信息模型“
    
git add user/views.py
git commit -m ”實現個人資料頁面“
    
git add tests/test_profile.py
git commit -m ”添加個人資料功能測試“   
  1. 推送到遠程
git push -u origin feature/user-profile    
  1. 創建Pull Request

    • 在GitHub/GitLab上發起PR
    • 同事審查代碼,提出建議
    • 根據反饋修改,再次推送
    • 通過CI/CD流水線的自動化測試
    • 合併到主分支
  2. 清理分支

git checkout main
git pull origin main
git branch -d feature/user-profile 

改變了什麼?

Git和它的衍生平台改變了三件事:

第一,降低了協作門檻。以前貢獻開源項目要發郵件、下源碼包、打補丁。現在點個Fork,改完提交PR就行。這讓開源從“精英遊戲”變成了“全民運動”。

第二,讓工作流標準化。無論你在哪個公司,用的都是相似的Git工作流。新人入職,半天就能上手代碼管理流程。

第三,創造了新的職業。DevOps工程師、平台開發,這些崗位很大程度上是因為Git生態出現的。

但最深層的改變,是思維方式的轉變。

我現在寫代碼時的心態完全不同了。知道有Git託底,就敢嘗試激進的重構。知道分支是安全的,就敢同時開展多個實驗性功能。知道每次提交都有記錄,寫commit message時會更認真。

尾聲

有時候我會想,如果2005年Linus沒被逼到必須自己寫工具,今天的世界會怎樣?

可能我們還在用QQ傳代碼壓縮包。可能開源不會這麼繁榮。可能遠程協作還是噩夢。

但歷史沒有如果。一個脾氣暴躁的程序員,花了十天時間解決自己的問題,順便解決了全世界程序員的問題。

這就是技術的魅力——最好的工具往往誕生於具體的困境,卻解決了普遍的需求。

現在每次我開始新項目,都會習慣性地git init。這個簡單的動作,連接着從個人備份到全球協作的整個歷史。

而每次git commit時,我知道自己不僅是在保存代碼。我是在參與一場持續了將近二十年的革命——一場讓創造變得更有序、更協作、更持久的革命。

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.