Git
English ▾ 主題 ▾ 最新版本 ▾ gittutorial 最後更新於 2.46.1

名稱

gittutorial - Git 的入門教學

概要

git *

說明

本教學說明如何將新專案匯入 Git、進行變更,以及與其他開發人員分享變更。

如果您主要對使用 Git 來取得專案(例如,測試最新版本)感興趣,您可能會比較喜歡從Git 使用者手冊的前兩章開始。

首先,請注意您可以使用以下命令取得如 git log --graph 之類的命令文件:

$ man git-log

$ git help log

後者可讓您使用您選擇的手冊檢視器;如需更多資訊,請參閱git-help[1]

在進行任何操作之前,最好先使用您的姓名和公開電子郵件地址向 Git 自我介紹。最簡單的方法是:

$ git config --global user.name "Your Name Comes Here"
$ git config --global user.email you@yourdomain.example.com

匯入新專案

假設您有一個包含初始工作的壓縮檔 project.tar.gz。您可以依照以下步驟將其置於 Git 版本控制之下。

$ tar xzf project.tar.gz
$ cd project
$ git init

Git 會回覆:

Initialized empty Git repository in .git/

您現在已初始化工作目錄 — 您可能會注意到建立了一個名為 .git 的新目錄。

接下來,使用 git add 命令告訴 Git 拍攝目前目錄下所有檔案內容的快照(請注意 .):

$ git add .

此快照現在儲存在一個 Git 稱為「索引」的暫存區域中。您可以使用 git commit 命令將索引的內容永久儲存在儲存庫中:

$ git commit

這會提示您輸入提交訊息。您現在已將專案的第一個版本儲存在 Git 中。

進行變更

修改一些檔案,然後將其更新後的內容新增至索引:

$ git add file1 file2 file3

您現在已準備好提交。您可以使用帶有 --cached 選項的 git diff 命令查看即將提交的內容:

$ git diff --cached

(如果沒有 --cachedgit diff 命令會顯示您已進行但尚未新增至索引的任何變更。)您也可以使用 git status 命令取得情況的簡短摘要:

$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)

	modified:   file1
	modified:   file2
	modified:   file3

如果您需要進行任何進一步的調整,請立即執行,然後將任何新修改的內容新增至索引。最後,使用以下命令提交您的變更:

$ git commit

這會再次提示您輸入描述變更的訊息,然後記錄專案的新版本。

或者,您可以使用以下命令來代替事先執行 git add

$ git commit -a

這會自動注意到任何修改過的(但不是新的)檔案,將它們新增至索引,並一步完成提交。

關於提交訊息的注意事項:雖然不是必須的,但最好在提交訊息的開頭加上一個簡短(不超過 50 個字元)的單行文字來總結變更,然後加上一個空行,然後再更詳細的說明。提交訊息中第一個空行之前的文字會被視為提交標題,該標題會在整個 Git 中使用。例如,git-format-patch[1] 會將提交轉換為電子郵件,並在主旨行使用標題,在內文中使用提交的其餘部分。

Git 追蹤內容,而不是檔案

許多版本控制系統都提供 add 命令,該命令會告訴系統開始追蹤新檔案的變更。Git 的 add 命令執行更簡單且更強大的操作:git add 用於新檔案和新修改的檔案,並且在這兩種情況下,它都會拍攝給定檔案的快照,並將該內容暫存於索引中,準備包含在下一次提交中。

檢視專案歷史記錄

您可以隨時使用以下命令檢視變更的歷史記錄:

$ git log

如果您也想查看每個步驟的完整差異,請使用:

$ git log -p

通常,變更的概述有助於了解每個步驟的感受:

$ git log --stat --summary

管理分支

單個 Git 儲存庫可以維護多個開發分支。若要建立一個名為 experimental 的新分支,請使用:

$ git branch experimental

如果您現在執行:

$ git branch

您將取得所有現有分支的清單:

  experimental
* master

experimental 分支是您剛建立的分支,而 master 分支是自動為您建立的預設分支。星號標記您目前所在的分支;輸入:

$ git switch experimental

切換至 experimental 分支。現在,編輯一個檔案、提交變更,然後切換回 master 分支:

(edit file)
$ git commit -a
$ git switch master

檢查您所做的變更是否不再可見,因為它是在 experimental 分支上進行的,而您現在回到 master 分支上。

您可以在 master 分支上進行不同的變更:

(edit file)
$ git commit -a

此時,這兩個分支已分歧,每個分支中都進行了不同的變更。若要將 experimental 中所做的變更合併到 master 中,請執行:

$ git merge experimental

如果變更沒有衝突,則您已完成。如果存在衝突,標記將會保留在顯示衝突的問題檔案中;

$ git diff

將會顯示此內容。一旦您編輯檔案以解決衝突,

$ git commit -a

將會提交合併的結果。最後,

$ gitk

將會顯示產生的歷史記錄的精美圖形表示。

此時,您可以使用以下命令刪除 experimental 分支:

$ git branch -d experimental

此命令確保 experimental 分支中的變更已在目前分支中。

如果您在 crazy-idea 分支上進行開發,然後又後悔了,您始終可以使用以下命令刪除分支:

$ git branch -D crazy-idea

分支很便宜且容易,因此這是嘗試新事物的好方法。

使用 Git 進行協作

假設 Alice 在 /home/alice/project 中使用 Git 儲存庫啟動了一個新專案,而 Bob (其在同一台機器上具有主目錄) 想要貢獻。

Bob 從以下命令開始:

bob$ git clone /home/alice/project myrepo

這會建立一個包含 Alice 儲存庫複製的新目錄 myrepo。此複製與原始專案地位相等,擁有原始專案歷史記錄的自己的副本。

然後,Bob 進行一些變更並提交它們:

(edit files)
bob$ git commit -a
(repeat as necessary)

當他準備好時,他會告訴 Alice 從 /home/bob/myrepo 的儲存庫提取變更。她使用以下命令執行此操作:

alice$ cd /home/alice/project
alice$ git pull /home/bob/myrepo master

這會將 Bob 的 master 分支中的變更合併到 Alice 的目前分支中。如果 Alice 同時進行了自己的變更,則她可能需要手動修正任何衝突。

因此,pull 命令會執行兩個操作:從遠端分支提取變更,然後將其合併到目前分支中。

請注意,通常,Alice 會希望在啟動此 pull 之前先提交她的本機變更。如果 Bob 的工作與 Alice 在他們的歷史記錄分叉之後所做的工作衝突,則 Alice 將使用她的工作樹和索引來解決衝突,並且現有的本機變更會干擾衝突解決流程(Git 仍然會執行提取,但會拒絕合併 — Alice 必須以某種方式擺脫她的本機變更,並在此情況發生時再次提取)。

Alice 可以先使用 fetch 命令查看 Bob 所做的事情,而無需先合併;這允許 Alice 使用一個特殊的符號 FETCH_HEAD 來檢查 Bob 所做的事情,以確定他是否有任何值得提取的東西,如下所示:

alice$ git fetch /home/bob/myrepo master
alice$ git log -p HEAD..FETCH_HEAD

即使 Alice 有尚未提交的本機變更,此操作也是安全的。範圍符號 HEAD..FETCH_HEAD 表示「顯示從 FETCH_HEAD 可到達的所有內容,但不包含從 HEAD 可到達的任何內容」。Alice 已經知道通往她目前狀態 (HEAD) 的所有內容,並且使用此命令檢閱 Bob 在他的狀態 (FETCH_HEAD) 中擁有的她尚未看到的内容。

如果 Alice 想要視覺化 Bob 自他們的歷史記錄分叉以來所做的事情,她可以發出以下命令:

$ gitk HEAD..FETCH_HEAD

這會使用我們先前在 git log 中看到的相同兩點範圍符號。

Alice 可能想要檢視他們在分叉後所做的所有事情。她可以使用三點形式來代替兩點形式:

$ gitk HEAD...FETCH_HEAD

這表示「顯示從任一可到達的所有內容,但不包含從兩者皆可到達的任何內容」。

請注意,這些範圍符號可以與 gitkgit log 一起使用。

在檢查 Bob 所做的事情後,如果沒有緊急的事情,Alice 可以決定在不從 Bob 提取的情況下繼續工作。如果 Bob 的歷史記錄確實有 Alice 需要立即使用的內容,Alice 可以選擇先存放她正在進行的工作,執行 pull,然後最終在產生的歷史記錄之上取消存放她正在進行的工作。

當您在一個小型的緊密團體中工作時,重複與同一個儲存庫互動是很常見的。透過定義 遠端 儲存庫的簡寫,您可以使其更容易:

alice$ git remote add bob /home/bob/myrepo

如此一來,Alice 可以單獨執行 pull 操作的第一部分,使用 git fetch 指令,而無需將其與自己的分支合併,使用方式如下:

alice$ git fetch bob

與完整形式不同的是,當 Alice 使用 git remote 設定的遠端儲存庫簡寫形式從 Bob 提取時,提取的內容會儲存在一個遠端追蹤分支中,在此案例中為 bob/master。因此,在此之後

alice$ git log -p master..bob/master

會顯示自 Bob 從 Alice 的 master 分支分支出來後,Bob 所做的所有變更清單。

在檢查這些變更之後,Alice 可以將這些變更合併到她的 master 分支中

alice$ git merge bob/master

這個 merge 也可以透過從她自己的遠端追蹤分支提取來完成,像這樣

alice$ git pull . remotes/bob/master

請注意,git pull 始終會合併到目前的分支,無論命令列上給定了什麼其他內容。

稍後,Bob 可以使用以下指令,以 Alice 的最新變更來更新他的儲存庫:

bob$ git pull

請注意,他不需要提供 Alice 儲存庫的路徑;當 Bob 克隆 Alice 的儲存庫時,Git 會將她儲存庫的位置儲存在儲存庫設定中,並且該位置會用於提取操作。

bob$ git config --get remote.origin.url
/home/alice/project

(使用 git config -l 可以看到 git clone 建立的完整設定,而 git-config[1] 的說明文件頁面則解釋了每個選項的含義。)

Git 也會將 Alice 的 master 分支的原始副本保留在名稱 origin/master 下。

bob$ git branch -r
  origin/master

如果 Bob 稍後決定從不同的主機工作,他仍然可以使用 ssh 協定來執行克隆和提取操作。

bob$ git clone alice.org:/home/alice/project myrepo

或者,Git 有一個原生協定,或可以使用 http;詳情請參閱 git-pull[1]

Git 也可以在類似 CVS 的模式下使用,其中有一個中央儲存庫,讓不同的使用者將變更推送至該儲存庫;請參閱 git-push[1]gitcvs-migration[7]

探索歷史記錄

Git 歷史記錄以一系列相互關聯的提交表示。我們已經看到 git log 指令可以列出這些提交。請注意,每個 git log 條目的第一行也會提供提交的名稱

$ git log
commit c82a22c39cbc32576f64f5c6b3f24b99ea8149c7
Author: Junio C Hamano <junkio@cox.net>
Date:   Tue May 16 17:18:22 2006 -0700

    merge-base: Clarify the comments on post processing.

我們可以將這個名稱提供給 git show 以查看有關此提交的詳細資訊。

$ git show c82a22c39cbc32576f64f5c6b3f24b99ea8149c7

但是還有其他方法可以參照提交。您可以使用名稱的任何初始部分,只要它夠長到可以唯一識別提交即可。

$ git show c82a22c39c	# the first few characters of the name are
			# usually enough
$ git show HEAD		# the tip of the current branch
$ git show experimental	# the tip of the "experimental" branch

每個提交通常都有一個「父」提交,該提交指向專案的先前狀態。

$ git show HEAD^  # to see the parent of HEAD
$ git show HEAD^^ # to see the grandparent of HEAD
$ git show HEAD~4 # to see the great-great grandparent of HEAD

請注意,合併提交可能有多個父提交。

$ git show HEAD^1 # show the first parent of HEAD (same as HEAD^)
$ git show HEAD^2 # show the second parent of HEAD

您也可以自行給予提交名稱;在執行

$ git tag v2.5 1b2e1d63ff

之後,您可以使用名稱 v2.5 來參照 1b2e1d63ff。如果您打算與其他人分享此名稱(例如,為了識別發行版本),您應該建立一個「標籤」物件,並可能對其進行簽署;詳情請參閱 git-tag[1]

任何需要知道提交的 Git 指令都可以使用這些名稱的任何一個。例如

$ git diff v2.5 HEAD	 # compare the current HEAD to v2.5
$ git branch stable v2.5 # start a new branch named "stable" based
			 # at v2.5
$ git reset --hard HEAD^ # reset your current branch and working
			 # directory to its state at HEAD^

請小心最後一個指令:除了遺失工作目錄中的任何變更之外,它還會從這個分支中移除所有後續提交。如果這個分支是唯一包含這些提交的分支,它們將會遺失。此外,請勿在其他開發人員從中提取的公開可見分支上使用 git reset,因為這會迫使其他開發人員執行不必要的合併以清理歷史記錄。如果您需要撤銷您已推送的變更,請改用 git revert

git grep 指令可以在您專案的任何版本中搜尋字串,因此

$ git grep "hello" v2.5

會在 v2.5 中搜尋所有出現的「hello」。

如果您省略提交名稱,git grep 將會在您目前目錄中管理的任何檔案中搜尋。所以

$ git grep "hello"

是一種快速搜尋 Git 追蹤的檔案的方法。

許多 Git 指令也會接受一組提交,這些提交可以透過多種方式指定。以下是一些使用 git log 的範例

$ git log v2.5..v2.6            # commits between v2.5 and v2.6
$ git log v2.5..                # commits since v2.5
$ git log --since="2 weeks ago" # commits from the last 2 weeks
$ git log v2.5.. Makefile       # commits since v2.5 which modify
				# Makefile

您也可以給予 git log 一個提交的「範圍」,其中第一個不一定是第二個的祖先;例如,如果分支 stablemaster 的頂端在很久之前從一個共同的提交分叉,那麼

$ git log stable..master

將列出在 master 分支中所做但不在 stable 分支中的提交,而

$ git log master..stable

則會顯示在 stable 分支中所做但不在 master 分支中的提交清單。

git log 指令有一個缺點:它必須以清單形式呈現提交。當歷史記錄中包含分叉然後合併回來的開發線時,git log 呈現這些提交的順序沒有意義。

大多數有多個貢獻者的專案(例如 Linux 核心或 Git 本身)都有頻繁的合併,而 gitk 在視覺化其歷史記錄方面做得更好。例如,

$ gitk --since="2 weeks ago" drivers/

可讓您瀏覽過去 2 週內修改 drivers 目錄下檔案的任何提交。(注意:您可以透過按住 control 鍵並同時按下「-」或「+」來調整 gitk 的字型。)

最後,大多數接受檔案名稱的指令都會選擇性地允許您在任何檔案名稱前面加上一個提交,以指定該檔案的特定版本。

$ git diff v2.5:Makefile HEAD:Makefile.in

您也可以使用 git show 來查看任何此類檔案。

$ git show v2.5:Makefile

下一步

本教學課程應足以執行您專案的基本分散式版本控制。但是,要完全了解 Git 的深度和力量,您需要了解其基於的兩個簡單概念

  • 物件資料庫是用於儲存您專案的歷史記錄(檔案、目錄和提交)的相當優雅的系統。

  • 索引檔案是一個目錄樹狀態的快取,用於建立提交、檢查出工作目錄,並保留合併中涉及的各種樹。

本教學課程的第二部分解釋了物件資料庫、索引檔案以及其他一些您需要充分利用 Git 的零星項目。您可以在 gittutorial-2[7] 中找到它。

如果您不想立即繼續執行該操作,則此時可能感興趣的其他一些題外話是

  • git-format-patch[1]git-am[1]:這些將一系列 git 提交轉換為透過電子郵件傳送的修補程式,反之亦然,對於嚴重依賴透過電子郵件傳送的修補程式的專案(例如 Linux 核心)非常有用。

  • git-bisect[1]:當您的專案中出現回歸時,追蹤錯誤的一種方法是透過搜尋歷史記錄來找出要歸咎的確切提交。git bisect 可以幫助您執行二元搜尋以尋找該提交。即使在具有大量合併分支的複雜非線性歷史記錄的情況下,它也足夠聰明能夠執行接近最佳的搜尋。

  • gitworkflows[7]:概述建議的工作流程。

  • giteveryday[7]:使用大約 20 個指令的日常 Git。

  • gitcvs-migration[7]:適用於 CVS 使用者的 Git。

GIT

git[1] 套件的一部分

scroll-to-top