簡體中文 ▾ 主題 ▾ 最新版本 ▾ 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

匯入新專案

假設您有一個包含您初始工作的 tarball project.tar.gz。您可以將其置於 Git 版本控制之下,如下所示。

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

Git 將回復

Initialized empty Git repository in .git/

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

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

$ 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

這會建立一個新目錄 myrepo,其中包含 Alice 倉庫的克隆。該克隆與原始專案地位相同,擁有原始專案歷史記錄的自己的副本。

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 仍將執行 fetch 但會拒絕合併 — Alice 將不得不以某種方式處理掉她的本地更改並在發生這種情況時再次 pull)。

Alice 可以不先合併就檢視 Bob 做了什麼,使用 fetch 命令;這允許 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 分支分叉以來所做的所有更改的列表。

檢查完這些更改後,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 clone 建立的完整配置可以使用 git config -l 檢視,並且 git-config[1] 手冊頁解釋了每個選項的含義。)

Git 還會在 origin/master 名稱下保留 Alice 的 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]:日常 Git,大約 20 個命令。

  • gitcvs-migration[7]:面向 CVS 使用者的 Git。

GIT

Git[1] 套件的一部分

scroll-to-top