1. 程式人生 > >git 使用詳解(3)—— 最基本命令 + .gitignore 文件

git 使用詳解(3)—— 最基本命令 + .gitignore 文件

clu 分隔 ignore abc lob 目的 hat modified 容易

Git 基礎

本章將介紹幾個最基本的,也是最常用的 Git 命令,以後絕大多數時間裏用到的也就是這幾個命令。讀完本章,你就能初始化一個新的代碼倉庫,做一些適當配置;開始或停止跟蹤某些文件;暫存或提交某些更新。我們還會展示如何讓 Git 忽略某些文件,或是名稱符合特定模式的文件;如何既快且容易地撤消犯下的小錯誤;如何瀏覽項目的更新歷史,查看某兩次更新之間的差異;以及如何從遠程倉庫拉數據下來或者推數據上去。

1. 在工作目錄中初始化新倉庫

要對現有的某個項目開始用 Git 管理,只需到此項目所在的目錄,執行:

$ git init

初始化後,在當前目錄下會出現一個名為 .git 的目錄,所有 Git 需要的數據和資源都存放在這個目錄中。不過目前,僅僅是按照既有的結構框架初始化好了裏邊所有的文件和目錄,但我們還沒有開始跟蹤管理項目中的任何一個文件。

如果當前目錄下有幾個文件想要納入版本控制,需要先用 git add 命令告訴 Git 開始對這些文件進行跟蹤,然後提交:

$ git add *.c
$ git add README
$ git commit -m ‘initial project version‘

現在,你已經得到了一個實際維護著若幹文件的 Git 倉庫

2. 從現有倉庫克隆

如果想對某個開源項目出一份力,可以先把該項目的 Git 倉庫復制一份出來,這就需要用到 git clone 命令。如果你熟悉其他的 VCS 比如 Subversion,你可能已經註意到這裏使用的是 clone 而不是 checkout。這是個非常重要的差別,Git 收取的是項目歷史的所有數據(每一個文件的每一個版本),服務器上有的數據 克隆 之後本地也都有了。實際上,即便服務器的磁盤發生故障,用任何一個克隆出來的客戶端都可以重建服務器上的倉庫,回到當初克隆時的狀態。

克隆倉庫的命令格式為 git clone [url]。比如,要克隆 Ruby 語言的 Git 代碼倉庫 Grit,可以用下面的命令:

$ git clone git://github.com/schacon/grit.git

這會在 當前目錄下 創建一個名為 “grit” 的目錄,其中包含一個 .git 的目錄,用於保存下載下來的所有版本記錄,然後從中取出最新版本 的文件拷貝。如果進入這個新建的 grit 目錄,你會看到項目中的所有文件已經在裏邊了,準備好後續的開發和使用。如果希望在克隆的時候,自己定義要新建的項目目錄名稱,可以在上面的命令末尾指定新的名字

$ git clone git://github.com/schacon/grit.git mygrit

唯一的差別就是,現在新建的目錄成了 mygrit,其他的都和上邊的一樣。

Git 支持許多數據傳輸協議。之前的例子使用的是 git:// 協議,不過你也可以用 http(s):// 或者user@server:/path.git 表示的 SSH 傳輸協議

3. 記錄每次更新到倉庫

現在我們手上已經有了一個真實項目的 Git 倉庫,並從這個倉庫中取出了所有文件的工作拷貝。接下來,對這些文件作些修改,在完成了一個階段的目標之後,提交本次更新到倉庫。

工作目錄下面的所有文件都不外乎這兩種狀態:已跟蹤或未跟蹤。已跟蹤的文件是指本來就被納入版本控制管理的文件,在上次快照中有它們的記錄,工作一段時間後,它們的狀態可能是未更新,已修改或者已放入暫存區。而所有其他文件都屬於未跟蹤文件。它們既沒有上次更新時的快照,也不在當前的暫存區域。初次克隆某個倉庫時,工作目錄中的所有文件都屬於已跟蹤文件,且狀態為 未修改。

在編輯過某些文件之後,Git 將這些文件標為已修改。我們逐步把這些修改過的文件放到暫存區域,直到最後一次性提交所有這些暫存起來的文件,如此重復。

3.1 檢查當前文件狀態

要確定 哪些文件 當前 處於 什麽狀態,可以用 git status 命令。如果在克隆倉庫之後立即執行此命令,會看到類似這樣的輸出:

$ git status
# On branch master nothing to commit (working directory clean)

這說明你

  • 現在的工作目錄 沒有任何文件在上次提交後更改過。
  • 此外,上面的信息還表明,當前目錄下沒有出現任何處於未跟蹤的新文件,否則 Git 會在這裏列出來。
  • 最後,該命令還顯示了當前所在的分支是 master,這是默認的分支名稱,實際是可以修改的。

現在讓我們用 vim 編輯一個新文件 README,保存退出後運行 git status 會看到該文件出現在未跟蹤文件列表中:

$ vim README
$ git status
# On branch master
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
# # README nothing added to commit but untracked files present (use "git add" to track)

就是在“Untracked files”這行下面。Git 不會自動將之納入跟蹤範圍,除非你明明白白地告訴它“我需要跟蹤該文件”,因而不用擔心把臨時文件什麽的也歸入版本管理。不過現在的例子中,我們確實想要跟蹤管理 README 這個文件。

3.2 跟蹤新文件

使用命令 git add 開始跟蹤一個新文件。所以,要跟蹤 README 文件,運行:

$ git add README

此時再運行 git status 命令,會看到 README 文件已被跟蹤,並處於暫存狀態:

$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
# # new file: README #

只要在 “Changes to be committed”這行下面的,就說明是已暫存狀態。如果此時提交,那麽該文件此時此刻的版本將被留存在歷史記錄中。你可能會想起之前我們使用 git init 後就運行了 git add 命令,開始跟蹤當前目錄下的文件。在 git add 後面可以指明要跟蹤的 文件 或 目錄 路徑。如果是目錄的話,就說明要遞歸跟蹤該目錄下的所有文件。

3.3 暫存已修改文件

現在我們修改下之前已跟蹤過的文件 benchmarks.rb,然後再次運行 status 命令,會看到這樣的狀態報告:

$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
# # new file: README
# # Changed but not updated:
# (use "git add <file>..." to update what will be committed)
# # modified: benchmarks.rb #

文件 benchmarks.rb 出現在 “Changed but not updated” 這行下面,說明已跟蹤文件的內容發生了變化,但還沒有放到 暫存區。要暫存這次更新,需要運行 git add 命令(這是個多功能命令,根據目標文件的狀態不同,此命令的效果也不同:可以用它開始跟蹤 新文件,或者把 已跟蹤的文件放到暫存區,還能用於合並時把 有沖突的文件標記為已解決狀態等)。現在讓我們運行 git add 將 benchmarks.rb 放到暫存區,然後再看看 git status 的輸出:

$ git add benchmarks.rb
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
#   new file: README
#   modified: benchmarks.rb #

現在兩個文件都已暫存,下次提交時就會一並記錄到倉庫。假設此時,你想要在 benchmarks.rb 裏再加條註釋,重新編輯存盤後,準備好提交。不過且慢,再運行 git status 看看:

$ vim benchmarks.rb
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
# # new file: README
#   modified: benchmarks.rb
# # Changed but not updated:
# (use "git add <file>..." to update what will be committed)
# # modified:
benchmarks.rb #

怎麽回事?benchmarks.rb 文件出現了兩次!一次算未暫存,一次算已暫存,這怎麽可能呢?好吧,實際上 Git 只不過暫存了你運行 git add 命令時的版本,如果現在提交,那麽提交的是添加註釋前的版本,而非當前工作目錄中的版本。所以,運行了 git add 之後又作了修訂的文件,需要重新運行 git add 把最新版本重新暫存起來:

$ git add benchmarks.rb
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
#   new file: README
#   modified: benchmarks.rb
#

忽略某些文件

一般我們總會有些文件無需納入 Git 的管理,也不希望它們總出現在未跟蹤文件列表。通常都是些自動生成的文件,比如日誌文件,或者編譯過程中創建的臨時文件等。我們可以在當前工程下創建一個名為 .gitignore 的文件,列出要忽略的文件模式。來看一個實際的例子:

$ cat .gitignore
*.[oa]
*~

第一行告訴 Git 忽略所有以 .o 或 .a 結尾的文件。一般這類對象文件和存檔文件都是編譯過程中出現的,我們用不著跟蹤它們的版本。第二行告訴 Git 忽略所有以波浪符(~)結尾的文件,許多文本編輯軟件(比如 Emacs)都用這樣的文件名保存副本。此外,你可能還需要忽略 log,tmp 或者 pid 目錄,以及自動生成的文檔等等。要養成一開始就設置好 .gitignore 文件的習慣,以免將來誤提交這類無用的文件。

文件 .gitignore 的格式規範如下:

所有`空行`或者以`註釋符號 # 開頭的行`都會被 Git  忽略。
可以使用標準的 glob 模式匹配。
 * 匹配模式最後跟反斜杠(/)說明要忽略的是目錄。
 * 要忽略指定模式以外的文件或目錄,可以在模式前加上驚嘆號(!)取反。
  所謂的 glob 模式是指 shell 所使用的簡化了的正則表達式。
    星號(*)匹配零個或多個任意字符;
    [abc] 匹配任何一個列在方括號中的字符(這個例子要麽匹配一個 a,要麽匹配一個 b,要麽匹配一個 c);
    問號(?)只匹配一個任意字符;
    如果在方括號中使用短劃線分隔兩個字符,表示所有在這兩個字符範圍內的都可以匹配(比如 [0-9] 表示匹配所有 0 到 9 的數字)。

我們再看一個 .gitignore 文件的例子:

# 此為註釋 – 將被 Git 忽略
*.a # 忽略所有 .a 結尾的文件
!lib.a # 但 lib.a 除外

/TODO # 僅僅忽略項目根目錄下的 TODO 文件,不包括 subdir/TODO
build/ # 忽略 build/ 目錄下的所有文件
doc/*.txt # 會忽略 doc/notes.txt 但不包括 doc/server/arch.txt

git 使用詳解(3)—— 最基本命令 + .gitignore 文件