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
文件,請移步 https://github.com/github/gitignore。
推薦閱讀:
※這些GIT經驗夠你用一年了
※IDE 有必要集成 Git 嗎?
※【Trac】瀏覽器中查看源碼庫
※Git常用命令詳解
※git怎麼控制成員的許可權?
TAG:Git |