Git 入門指南

git 是如今最為著名的 DVCS (Distributed Version Control Systems),它是由被稱為「Linux 之父」的 「Linus Torvalds」 先生於 2005 年製作的。git 不但有強大的功能,更是一個不妥協的產物,其誕生的歷史融合了計算機大師的自嘲和自由軟件開發者的反抗精神,令筆者非常敬佩。

下面引用維基百科中文版對這段軼事的描述(原文鏈接這裡,英文版本鏈接這裡):

自 2002 年開始,林納斯·托瓦茲(Linus Torvalds)決定使用 BitKeeper 作為 Linux 內核主要的版本控制系統用以維護程式碼。因為 BitKeeper 為專有軟體,這個決定在社群中長期遭受質疑。在 Linux 社群中,特別是理查德·斯托曼(Richard Stallman)與自由軟體基金會的成員,主張應該使用開放原始碼的軟體來作為 Linux 核心的版本控制系統。林納斯·托瓦茲曾考慮過採用現成軟體作為版本控制系統(例如 Monotone),但這些軟體都存在一些問題,特別是效能不佳。現成的方案,如 CVS 的架構,受到林納斯·托瓦茲的批評。

2005 年,安德魯·垂鳩(Andrew Tridgell)寫了一個簡單程式,可以連接 BitKeeper 的儲存庫,BitKeeper 著作權擁有者拉里·麥沃伊(Larry McVoy)認為安德魯·垂鳩對 BitKeeper 內部使用的協議進行逆向工程,決定收回無償使用 BitKeeper 的授權。Linux 內核開發團隊與 BitMover 公司進行蹉商,但無法解決他們之間的歧見。林納斯·托瓦茲決定自行開發版本控制系統替代 BitKeeper,以十天的時間,編寫出第一個 git 版本。

git 不僅僅是一個為程序員所用的版本控制工具,還受到了廣泛的歡迎,並且成為了一個方便快捷的多人協作工具。很多資料的收集、文章的創作可以使用 git 完成,這讓學習 git 的價值大大增加,是學習與生活的必備良品。

本篇文章延續了筆者一貫的教程風格,旨在幫助大家快速入門。如果想要更深入的學習,筆者還是推薦閱讀官方手冊,關於 git 的資料可以參考以下鏈接:

知名的 git 服務提供網站:

以下是正文,望各位看官品閱,如有錯誤還請郵件指正~

目錄

第一步:創建或獲取 repo

在使用 git 之前,我們首先需要創建或獲取一個 git repository(以下簡稱 repo)。我們可以通過以下兩種方式來建立 repo

本地創建

在本地創建 repo 的方式非常簡單。首先,進入我們希望設置 repo 的目錄:

$ cd /my/git/repo

然後,使用 git init 命令初始化 repo

$ git init

執行後,當前目錄下會多出一個名為 .git 的隱藏目錄,這裡存儲了 git 的所有內部數據和版本控制信息。我們通常不需要直接操作這個目錄,而是通過 git 命令來管理 repo

網上獲取

如果我們希望使用網路上已有的 repo,可以從遠程服務 clone 它。首先,導航到我們希望存放 repo 的本地目錄,然後執行:

$ git clone <url>

這條命令會下載遠程 repo 的所有內容,包括歷史記錄,並且自動為我們設置好 remote(下文會提到)。

使用上述兩種方式建立 repo 後,我們就正式進入 git 的世界,開始版本控制的旅程!

第二步:留名青史

在使用 git 之前,我們首先需要設置個人信息(最重要的兩個信息是姓名和電子郵件)。這樣,當其他人在查看我們的項目時,如果遇到問題,就能夠聯繫到我們。同時,在團隊協作中,這也有助於追蹤每個人的提交記錄,確保責任明確。此外,保留個人信息也有助於保護自身的貢獻權益。尤其是在開源項目中,能夠看到自己的名字被記錄在 git 日誌中,或許還會有些小小的成就感。

更重要的是,個人信息一旦設置,特別是在大型項目或他人的 repo 中,後續修改可能會比較麻煩。對於筆者這樣的強迫症患者來說,這簡直是一場噩夢。筆者剛開始使用 git 時,沒有設置個人信息,結果導致所有的 git log 記錄都顯示的是電腦默認的名稱,看起來相當不美觀。因此,建議在初次使用 git 時,就設置好全局的個人信息,以免日後產生不必要的困擾。

我們可以通過以下命令來設置全局個人信息,使其適用於所有 repo

$ git config --global user.name "Your Name"
$ git config --global user.email "your-email@example.com"

當然,如果我們只想在特定 repo 中使用不同的信息,而不影響全局設置,可以使用 --local 參數,方法如下:

$ git config --local user.name "Your Name"
$ git config --local user.email "your-email@example.com"

如果需要查閱更多配置選項,可以參考 git config 手冊:

$ man git config

如果想確認當前的配置信息,可以使用以下命令來列出所有 git 配置:

$ git config -l

當我們確認個人信息設置完畢後,就可以正式開始使用 git 進行版本控制了!

第三步:記錄改變

現在,我們要正式進入 git 的核心功能:版本控制的記錄機制。作為一個版本控制系統 (VCS),git 的主要作用就是追蹤和管理文件的變更。在 git 中,文件主要有兩種狀態:

下面這張來自 git 官網 的圖片清晰地展示了 git 如何管理文件的狀態流轉:

The lifecycle of the status of your files (source from git-scm.com)

檢查文件狀態

我們可以使用以下命令來檢查當前 repo 中的文件狀態:

$ git status

執行該命令後,我們可以看到哪些文件處於 untrackedmodifiedstaged 狀態。這對於掌握當前 repo 的變更情況至關重要。

如果想要深入了解 git 的運作方式,建議參閱官網提供的參考書,本文則專注於幫助讀者快速上手。

追蹤新文件

如果我們在 repo 中新建了一個名為 README 的文件:

$ touch README

此時,該文件處於 untracked 狀態。為了讓 git 追蹤它,我們需要使用以下命令:

$ git add README

這樣,該文件便進入 staged 狀態,等待 commit

commit 變更

當文件進入 staged 狀態後,我們可以將其 commitrepo 中:

$ git commit

執行此命令後,git 會打開默認的 editor,讓我們輸入此次提交的描述信息,確保日後能夠清楚回顧每次變更的原因。完成編輯後,該文件便進入 unmodified 狀態。

通常,commit 變更的標準流程如下:

$ git add <file>  # 暫存變更
$ git commit      # commit 變更

簡化記錄操作

為了提高效率,我們可以使用以下命令一次性 commit 所有變更:

$ git add -A  # 添加所有變更的文件(等同於 --all)
$ git commit -m "簡要描述本次 commit 內容"  # 直接添加 commit 信息,無需進入編輯器

這樣,我們就成功完成了 git 的基本變更記錄流程,這也是日常使用中最常見的一些操作。

第四步:查看歷史記錄和變更內容

當我們開始使用 git 進行版本控制後,難免會有查看過去修改記錄的需求。前面提到的 git status 只能顯示當前的工作區狀態,而如果想要查閱完整的修改歷史,就需要使用:

$ git log

這條命令會列出所有 commit 記錄,包括 commithash、作者、日期和提交信息。有心的讀者可能會注意到,每次提交都對應著一個 hash 值 ,這就相當於該次修改的「身份標識」。當我們需要回溯到某個特定的時間點,這串 hash 值就派上用場了。

除了查看 commit 記錄,有時我們還需要檢視具體的變更內容,而不只是知道哪些文件被修改了。這時候,git diff 命令就非常有用。

查看未 staged 的變更

如果想要查看工作目錄中已修改但尚未 git add 的變更,可以使用:

$ git diff

這條命令會顯示具體的變更內容,包括新增 (+) 和刪除 (-) 的部分,讓我們能夠清楚地看到修改了哪些行。

如果我們希望以單詞為單位來查看變更,而不是整行對比,可以使用 --word-diff 參數:

$ git diff --word-diff

這將以 [-刪除的內容-]{+新增的內容+} 的格式標示變更,使其更加直觀,特別適用於修改較少但影響較大的情況。

如果想要更加精細的甄別,可以使用:

$ git diff --word-diff-regex=.

這會將每個字符視為單獨的比較單位,對於像中文這樣的語言來說特別有用,因為單個字符就可能具有意義。

查看已經 staged 的變更

如果文件已經 git addstaged 階段,但尚未 commit,想要檢視這部分變更內容,可以使用:

$ git diff --staged

這條命令與 git diff 類似,但它專門顯示已 staged 但尚未 commit 的修改,幫助我們確認即將 commit 的內容是否符合預期。

查看兩次 commit 之間的變更

有時我們需要比較兩個不同的 commit,了解它們之間的差異,可以使用:

$ git diff <commit-hash-1> <commit-hash-2>

這樣,我們可以清楚地看到兩次 commit 之間的變更內容,方便追蹤修改歷程。

這些 git diff 命令對於版本管理至關重要,能夠幫助我們更清楚地理解變更的細節,使我們在 git 的工作流中更得心應手。

第五步:撤銷變更內容

除了查看歷史記錄和變更的內容,我們經常還需要撤銷變更內容。回溯到某個 commit 的時間點是 git 使用過程中經常遇到的需求。使用以下命令,git 會讓 repo 恢復到指定 commit 的狀態:

$ git reset <commit-hash>

需要注意的是,這個命令主要影響 gitcommit 記錄,而不會對文件本身進行刪除。例如,如果某個文件在該 commit 之前是 untracked(未被 git 追蹤),則 reset 後它仍然處於 untracked 狀態,不會自動消失,這個文件會變成 unstaged 的狀態。

--soft 選項:保留修改內容

如果希望回溯 commit 記錄,但仍然保留修改內容在 staged 中,可以使用 --soft 參數:

$ git reset --soft <commit-hash>

這樣,該 commit 之後的修改仍然會保留在 staged 狀態,允許我們進一步修改或重新 commit

--hard 選項:完全恢復到指定 commit

如果想要完全清除 commit 之後的所有變更(包括工作區和 staged 狀態的文件),則可使用 --hard 參數:

$ git reset --hard <commit-hash>

這將強制回滾到指定 commit,所有 commit-hash 之後的變更都會被徹底刪除,無法找回。因此,請務必謹慎操作,確保不會誤刪重要內容。

選擇 git reset 的不同模式取決於你的需求,如果只是想撤銷 commit 但保留修改內容,--soft 會是更好的選擇,而如果確定要回滾所有變更,則 --hard 會提供最徹底的清理方式。

第六步:遠程管理

git 的使用過程中,remote repository(以下簡稱 remote)的管理是團隊協作和代碼備份的關鍵部分。我們經常需要將本地代碼同步到 remote,或者從中獲取最新的代碼,以確保開發進度的一致性。

已經存在遠程 repo

假設我們已經有了一個 remote,那麼在本地我們需要先 init 一個 repo,然後添加 remote 的鏈接:

$ git remote add origin <URL>  # origin 是一個我們可以修改的簡稱
$ git remote -v  # 查看鏈接情況

成功鏈接後,我們可以 pull 這個 remote 以獲取最新的代碼:

$ git pull origin master  # origin 是 remote 名稱,而 master 則是 branch 名稱

有人可能會問,這與 git clone 有何不同?簡單來說,clone 是直接複製 remote 的內容到本地,而 git remote 命令則是建立本地與遠程的關聯,讓我們可以手動管理 pushpull 操作。

當我們完成本地修改後,可以使用以下命令將變更 pushremote

$ git push origin master

強制從遠程服務器 pull 並覆蓋本地 repo

有時候我們本地的 repo 可能與 remote 的歷史發生衝突,這時可以強制同步遠程版本,覆蓋本地變更。請謹慎使用以下命令,因為它會刪除所有本地的修改(包括已經 commit 的):

$ git fetch --all
$ git reset --hard origin/master
$ git pull origin master

這樣,本地代碼就會與 remote 完全同步。

已經存在本地 repo

如果我們在本地已經有了一個 repo,並且希望將其上傳到 remote,那麼我們需要先在 remote 的服務上創建一個新的空 repo,然後在本地執行以下命令來建立關聯並 push 已有的內容:

$ git remote add origin <URL>
$ git add .
$ git commit -m "Initial commit"
$ git push origin master

由於 git push 是我們最常使用的命令之一,為了方便未來的操作,可以使用 -u 參數來設置默認上傳的 remotebranch

$ git push -u origin master

這樣,以後只需要簡單執行:

$ git push

就能將本地變更 pushremote,極大地提升了開發效率。

總結

恭喜 :) 本篇文章到此告一段落!我們剛剛介紹了 git 的基礎用法,希望各位看官在瀏覽後能夠快速上手,開始使用 git 進行版本控制。不過,git 的學習之路遠不止於此,即使完全掌握了本文的內容,也只是入門的第一步。

與許多 Unix-like 工具一樣,git 需要通過持續的學習和實踐才能真正熟練運用,並深入理解其中的奧妙。如果你希望進一步探索 git 的進階操作,可以參閱筆者的「Git 進階指南:實用技巧與最佳實踐」

祝願各位在 git 的學習之路上,一帆風順!