標籤:

git文件的操作

什麼是git倉庫?

讓我們來重溫一下三個區域的概念:

git有三個工作區域:工作目錄(Working Directory),暫存區(Staging Area)和git倉庫(.git directory)(Repository)。

在每個git項目的根目錄下,都會有一個.git目錄,這個目錄就是git倉庫。暫存區是git倉庫中的一個文件(index文件),它保存著下次要提交到git倉庫的文件列表。

作為分散式版本控制系統,git中的git倉庫被保存在每一份項目文件中,而沒有中央服務倉庫。

我們平時工作的地方,也就是項目的文件夾,叫做工作目錄。

一個git倉庫包括:

  • 一系列提交對象(commit objects).
  • 一系列指向這些提交對象的索引,叫做heads。

一個提交對象(commit objects)包括:

  • 一系列文件在某個時間的快照。
  • 一系列指向父提交對象的索引。
  • 一個SHA-1名字,這個名字40個字元長,是獨一無二的。
  • 作者的姓名和郵箱,以及提交時對提交的描述。

用戶在修改完版本A後提交得到版本B,版本A就是版本B的父提交對象。一個提交對象可以有多個父提交對象。

整個項目中的第一個提交對象沒有父提交對象。

總的來說,git倉庫包含很多提交對象,並且每個提交對象都指向自己的父提交對象,直到第一個提交對象。

head與HEAD

head只是一個指向提交對象的索引,每一個head都有一個名字。git默認有一個叫做master的head。一個git倉庫可以有多個head。

在任何時候,當前使用的head的別名叫作HEAD

每一次提交之後,HEAD都會自動地從父提交對象指向本次提交對象。

綜上所述,git倉庫的示意圖如下:

在提交之後,會生成新的提交對象,並且HEAD會指向新的提交對象。

修改了什麼?git diff [--staged]

現在將README.txt文件中的最後一行Git is very fast.修改為Git is very fast and convenient.可以得到如下結果:

$ git diffdiff --git a/README.txt b/README.txtindex f3401b9..a695b86 100644--- a/README.txt+++ b/README.txt@@ -1,3 +1,4 @@ Hi, Git! Git is a free and open source distributed version control system. Git is very easy to learn.+Git is very fast and convenient.$ git add README.txt $ git diff$

可見,git diff將工作目錄中現在的文件狀態同暫存區中的文件相比較。如果要比較暫存區中下次要提交文件同已提交文件的更改,可以使用git diff --staged命令,這個命令會比較HEAD指向的文件版本與暫存區中的版本的區別(git diff --cached是此命令的老用法):

$ git diff --stageddiff --git a/README.txt b/README.txtindex f14261d..a695b86 100644--- a/README.txt+++ b/README.txt@@ -1,2 +1,4 @@ Hi, Git! Git is a free and open source distributed version control system.+Git is very easy to learn.+Git is very fast and convenient.

就像之前所說,HEAD指向當前的提交對象,因此git diff HEAD -- README.txt可以比較當前git倉庫中的文件版本和工作目錄中的文件版本。

移除文件 git rm [-f | --cached]

如果要從已被跟蹤的文件列表中刪除某個文件,可以使用git rm命令,它會同時刪除工作目錄中的文件。如果文件已經被修改並且納入暫存區,那麼需要使用-f選項。下面是一個例子,省略了部分輸出:

$ touch a.txt$ git add a.txt$ git commit -m "add a.txt"$ lsa.txt README.txt$ git rm a.txtrm a.txt$ git statusOn branch masterChanges to be committed: (use "git reset HEAD <file>..." to unstage) deleted: a.txt$ git commit -m "delete a.txt"$ lsREADME.txt

如果仍然需要在工作目錄中使用該文件,而不想被跟蹤,可以使用--cached選項。

$ touch b.txt$ git add b.txt$ git commit -m "add b.txt"$ git rm --cached b.txt$ git commit -m "delete cached b.txt"$ git statusOn branch masterUntracked files: (use "git add <file>..." to include in what will be committed) b.txtnothing added to commit but untracked files present (use "git add" to track)

重命名文件 git mv

使用git mv命令對文件進行重命名:

$ git mv README.txt README.md$ git statusOn branch masterChanges to be committed: (use "git reset HEAD <file>..." to unstage) renamed: README.txt -> README.md

忽略文件 .gitignore

項目中可能有一些文件不需要,或者不應該被git跟蹤,比如私人配置文件、日誌文件、臨時文件等。這時候就用到了.gitignore文件,最好在項目一開始就配置好這個文件,以免將來錯誤的提交此類文件。.gitignore文件中記錄的文件列表不會被git跟蹤。

現在以a.txt為例,將它加到.gitignore文件中:

$ echo "a.txt" >> .gitignore$ git add .gitignore ; git commit -m "add a.txt to .gitignore"$ touch a.txt$ git statusOn branch masternothing to commit, working directory clean

可見,雖然a.txt是新的文件,但是git卻現實工作目錄是乾淨的,原因就是a.txt被加到了.gitignore中。

.gitignore文件的語法如下:

  • 開頭的行表示注釋,都會被 Git 忽略。
  • 可以使用標準的 glob 模式匹配。
  • 匹配模式可以以(/)開頭防止遞歸。
  • 匹配模式可以以(/)結尾指定目錄。
  • 要忽略指定模式以外的文件或目錄,可以在模式前加上驚嘆號(!)取反。

標準的glob模式指的是:

  • *表示匹配零或者任意多個任意字元;
  • [abc]表示匹配括弧中的任意一個字元,此例表示比配一個a,或者一個b,或者一個c。
  • ?表示匹配任意一個字元;
  • 方括弧中用短線表示斷線兩端內的字元會被匹配,[0-9]表示會匹配0至9之間的數字。
  • **表示任意中間目錄,比如a/**/z匹配a目錄中的z文件,中間可以有零至多級目錄。

下面的例子來自《Pro Git》(written by Scott Chacon and Ben Straub and published by Apress)書籍,2.2節,遵循Creative Commons Attribution Non Commercial Share Alike 3.0 license協議。本文遵循相同協議。我對原本例子進行了翻譯。這是一個.gitignore文件的例子:

# 忽略 .a 文件*.a # 跟蹤 lib.a, 即使在上一句中已經忽略了 .a 文件 !lib.a # 僅僅忽略本目錄的 TODO,不要忽略子目錄的 TODO/TODO # 忽略 build 目錄中的所有文件build/ # 忽略 doc/notes.txt, 但會跟蹤 doc/server/arch.txt doc/*.txt # 忽略所有的 doc/ 目錄中的 .pdf 文件doc/**/*.pdf

GitHub上有數十種語言的.gitignore文件,請移步 github.com/github/gitig


推薦閱讀:

這些GIT經驗夠你用一年了
IDE 有必要集成 Git 嗎?
【Trac】瀏覽器中查看源碼庫
Git常用命令詳解
git怎麼控制成員的許可權?

TAG:Git |