分类:Git| 发布时间:2014-03-03 01:36:09
本文主要介绍如何管理index和你的文件。在Git中如何增加、 删除以及重命名文件,如何登记index文件的状态。 最后还讲了.gitignore文件以及相关规则。
当你使用git commit提交修改时,Git根据你的index而不是工作目录来确定要提交的东西。 你可以通过git status来查看index的状态。 你可以通过git diff来查看工作目录和index的差异,而通过git diff --cached可以查看当前的HEAD和index的差异。
下面来看一个实例:
$ mkdir my_stuff
$ cd my_stuff/
$ git init
Initialized empty Git repository in g:/src/my_stuff/.git/
$ git status
# On branch master
#
# Initial commit
#
nothing to commit (create/copy files and use "git add" to track)
$ echo "New data" > data
$ git status
# On branch master
#
# Initial commit
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# data
nothing added to commit but untracked files present (use "git add" to track)
初始情况下,代码库是没有文件的。因此 staged、ignore和untracked类型的文件集都是空的。 当你添加了一个文件后,git status报告有一个untracked的文件。 在你的工作环境或者编译环境中,通常会有临时文件。这种文件不应该作为代码库的源文件。 如果你需要忽略一个文件,你需要做的只是将这个文件添加到.gitignore文件中。
$ touch main.o
$ git status
# On branch master
#
# Initial commit
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# data
# main.o
nothing added to commit but untracked files present (use "git add" to track)
$ echo main.o > .gitignore
$ git status
# On branch master
#
# Initial commit
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# .gitignore
# data
nothing added to commit but untracked files present (use "git add" to track)
可以看到,main.o已经被忽略了,但是需要注意的是:虽然.gitignore对于Git来说是有特殊意义的, 但Git也会将.gitignore作为代码库中的普通文件来管理。
git add用于stages一个文件。如果一个文件是untracked的,git add会将这个文件的状态变为tracked。 如果git add是用于一个目录的,那么这个目录的所有文件和子目录都会被staged。
让我们继续上一节的例子:
$ git status
# On branch master
#
# Initial commit
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# .gitignore
# data
nothing added to commit but untracked files present (use "git add" to track)
$ git add data .gitignore
$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached <file>..." to unstage)
#
# new file: .gitignore
# new file: data
#
可以看到在使用git add之后,两个文件由untracked变为tracked了。 并且这两个文件将会在下一次提交的时候正式添加到代码库中。 根据Git的对象模型,当你使用git add的时候,整个文件的内容会被复制到object store。 Staging一个文件又被称为“缓存一个文件”或者“将一个文件放到目录中”。
你可以通过git ls-files查看那些staged的文件的SHA1值和文件名:
$ git ls-files --stage
100644 0487f44090ad950f61955271cf0a2d6c6a83ad9a 0 .gitignore
100644 534469f67ae5ce72a7a274faf30dee3c2ea1746d 0 data
如果你修改了一些还没提交的文件(已经用git add staged了这个文件), 那么你需要再次使用git add更新这个文件。 否则将会有两个版本的文件,一个版本是git add时的,另一个是你工作目录的。
我们继续上面的例子来演示这种情况:
$ git ls-files --stage
100644 0487f44090ad950f61955271cf0a2d6c6a83ad9a 0 .gitignore
100644 534469f67ae5ce72a7a274faf30dee3c2ea1746d 0 data
# 将data的内容修改为
$ cat data
New data
And some more data now
$ git hash-object data
e476983f39f6e4f453f0fe4a859410f63b58b500
$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached <file>..." to unstage)
#
# new file: .gitignore
# new file: data
#
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: data
#
当文件修改后,在object store和index文件中的data的SHA1是 534469f67ae5ce72a7a274faf30dee3c2ea1746d, 但是我们工作目录中的data的SHA1是 e476983f39f6e4f453f0fe4a859410f63b58b500 。
让我们更新这个文件到object store和index文件中:
$ git add data
$ git ls-files --stage
100644 0487f44090ad950f61955271cf0a2d6c6a83ad9a 0 .gitignore
100644 e476983f39f6e4f453f0fe4a859410f63b58b500 0 data
$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached <file>..." to unstage)
#
# new file: .gitignore
# new file: data
#
可以在使用git add 或 git commit命令时添加--interactive参数来进行交互式的操作。
在git commit时使用-a 或者 --all 选项会在提交之前自动将所有 tracked文件的修改(包括那些tracked文件的删除)staged。
如果你是在编辑器中编写日志信息,并且由于某些原因想取消提交, 那么直接退出编辑器并且不保存内容就行了。 但是如果你已经保存了信息,但是没退出编辑器, 那么需要将日志信息清空然后保存再退出从而取消提交。
git rm用于删除一个文件,很自然地可以认为它是git add的反操作。 但是因为错误地删除一个文件有可能会导致问题发生,所以Git会更认真地对git rm进行检查。
继续上一节的例子:
$ echo "Random stuff" > oops
$ git rm oops
fatal: pathspec 'oops' did not match any files
因为git rm也会对index文件进行操作,这个命令不会删除那些不在Git仓库或者index中的文件。
$ git add oops
$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached <file>..." to unstage)
#
# new file: .gitignore
# new file: data
# new file: oops
#
可以使用git rm --cached将一个文件从staged转为unstaged:
$ git ls-files --stage
100644 0487f44090ad950f61955271cf0a2d6c6a83ad9a 0 .gitignore
100644 e476983f39f6e4f453f0fe4a859410f63b58b500 0 data
100644 fcd87b055f261557434fa9956e6ce29433a5cd1c 0 oops
$ git rm --cached oops
rm 'oops'
$ git ls-files --stage
100644 0487f44090ad950f61955271cf0a2d6c6a83ad9a 0 .gitignore
100644 e476983f39f6e4f453f0fe4a859410f63b58b500 0 data
使用git rm --cached会将一个文件从index中删除,但会保留在工作目录中。
如果你希望在下一次提交时删除文件,只需要使用git rm命令:
$ git add data .gitignore
$ git commit -m "Add some files"
[master (root-commit) f917c45] Add some files
2 files changed, 3 insertions(+)
create mode 100644 .gitignore
create mode 100644 data
$ git rm data
rm 'data'
$ rm oops
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# deleted: data
#
需要注意的是在使用git rm时,Git会检查工作目录的文件是否和 当前分支的最新提交中的文件一致,如果不一致Git会拒绝删除。 当然你可以使用git rm -f强制删除这个文件,而不检查是否一致。
如果你希望将删除的文件重新添加回来,你首先可能会想到以下命令:
$ git add data
fatal: pathspec 'data' did not match any files
糟!git rm删除了工作目录的文件。 那应该怎么办呢?别担心,版本管理系统很擅长恢复旧版本的文件。
$ git checkout HEAD -- data
$ git status
# On branch master
nothing to commit, working directory clean
$ cat data
New data
And some more data now
可以使用git mv来移动文件:
$ git mv data mydata
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# renamed: data -> mydata
#
$ git commit -m"Moved data to mydata"
[master 9ad02b5] Moved data to mydata
1 file changed, 0 insertions(+), 0 deletions(-)
rename data => mydata (100%)
如果你使用git log来查看重命名后的文件的日志,你会发现只有这么一条:
$ git log mydata
commit 9ad02b5370332ce5b00d3d78135cf6cd5ea5ce7e
Author: Jianlong Chen <jianlong99@gmail.com>
Date: Thu Jan 30 13:12:44 2014 +0800
Moved data to mydata
如果要查看完整的历史,可以使用--follow参数:
$ git log --follow mydata
commit 9ad02b5370332ce5b00d3d78135cf6cd5ea5ce7e
Author: Jianlong Chen <jianlong99@gmail.com>
Date: Thu Jan 30 13:12:44 2014 +0800
Moved data to mydata
commit f917c4539b5a923f6f19ab8dc2fb58f0c65163c3
Author: Jianlong Chen <jianlong99@gmail.com>
Date: Thu Jan 30 13:01:14 2014 +0800
Add some files
.gitignore文件的格式如下:
每个目录都可以有.gitignore的,关于.gitignore的优先级如下(由高到低):
在.gitignore中的规则是全局的,而.git/info/exclude和core.excludefile 中的规则在git clone时不会被复制。