可以认为使用Git时,我们会遇到3个空间:工作目录、索引、版本库。我们关心的,就是在新建、修改等操作时,这三者之间发生了怎样的变化。
笼统的讲,就是在工作目录下编辑,在索引中积累修改,然后把索引中累计的修改作为一次性的变更提交给版本库。
这就意味着,可以在最终提交前添加、删除、移动或者重复编辑文件,只有在提交后才会在版本库里实现累计的变更。
本章将介绍如何管理索引和文件。
一、关于索引的一切:
Git的索引不包含任何文件内容,它仅仅追踪你想要提交的那些内容。这一点,我们可以在后面的图示中看到。当git commit时,会通过检查索引而不是工作目录来找到提交的内容。
在暂存的过程中,git diff将会是一个非常有用的命令。
git diff 显示仍留在工作目录中且为暂存的变更。
git diff –cached 显示已经暂存并且要在下一次提交的变更。
二、Git中的文件分类:
Git将所有的文件分为3类:已追踪的、被忽略的、未追踪的。
- 已追踪的:指已经在版本库中的文件,或者是已暂存到索引中的文件。
- 被忽略的:在版本库中被明确声明为不可见或被忽略的文件。
- 未追踪的:除去上面两类文件。
这里通过创建一个全新的工作目录并处理一下文件来看一下这些不同类别的文件。
在工作目录中经常会产生一下临时文件,在版本库中这些文件通常是不应该被当做源文件追踪的。
为了让Git忽略这些文件,只需要将该文件名添加到一个特殊的文件.gitignore中就可以了
上图中的步骤中我们看到了这种变化。需要注意的是,虽然.gitignore对于Git是个特殊的文件,但是也需要手动的添加到索引中。
三、使用git add:
git add将暂存一个文件。看看例子就好了。
[root@flower1 my_stuff]# 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) [root@flower1 my_stuff]# git add data .gitignore [root@flower1 my_stuff]# git status # On branch master # # Initial commit # # Changes to be committed: # (use "git rm --cached <file>..." to unstage) # # new file: .gitignore # new file: data #
[root@flower1 my_stuff]# git ls-files --stage
上面的这个实验蛮有意思。当我们修改了data这个文件后,文件本身的SHA1散列码已经改变,但是git ls-files –stage没有发生变化。只有到使用git add命令后才发生变化。这是因为,索引之后指向已经存在于对象库中的blob对象。
四、使用git commit的一些注意事项:
git commit -a或者-all选项会导致执行提交前自动暂存所有未暂存的和未追踪的文件变化,包括从工作副本中删除已追踪的文件。
做个试验来验证一下。这里就不截图了。
试验的结果是:上面的说法感觉有歧义。所谓的自动暂存,是有前提的,前提是这些文件本身就已经在版本库中或者已经在索引中。(这是我测试的结果,不知是否真的正确)
五、使用git rm:
Git可以在索引中或者同时在索引和工作目录中删除一个文件,但是不能删除该文件在版本库中的历史记录。
git rm -f file1会从索引和工作目录中同时删除
git rm –cached file2 仅删除索引中的文件
下面验证一下:
[root@flower1 committest]# ls newfile notyet.txt ready.txt [root@flower1 committest]# rm newfile rm: remove regular file `newfile'? y [root@flower1 committest]# ls notyet.txt ready.txt [root@flower1 committest]# echo "new file" > newfile [root@flower1 committest]# ls newfile notyet.txt ready.txt [root@flower1 committest]# git add newfile [root@flower1 committest]# git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # new file: newfile # [root@flower1 committest]# git rm --cached newfile rm 'newfile' [root@flower1 committest]# git status # On branch master # Untracked files: # (use "git add <file>..." to include in what will be committed) # # newfile nothing added to commit but untracked files present (use "git add" to track) [root@flower1 committest]# ls newfile notyet.txt ready.txt
上面的试验,使用了—cached参数,工作目录中的文件没有删除。
[root@flower1 committest]# git add newfile [root@flower1 committest]# git rm -f newfile rm 'newfile' [root@flower1 committest]# ls notyet.txt ready.txt
想要移除一个已经提交的文件,通过git rm和git commit的组合命令即可实现。
六、使用git mv:
这里仅用命令行说明一下吧 。
[root@flower1 committest]# ls notyet.txt ready.txt [root@flower1 committest]# git mv ready.txt ready.txt.bak [root@flower1 committest]# git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # renamed: ready.txt -> ready.txt.bak # [root@flower1 committest]# git commit -m "new data ty" [master 2a9b527] new data ty 1 files changed, 0 insertions(+), 0 deletions(-) rename ready.txt => ready.txt.bak (100%) [root@flower1 committest]# git log ready.txt.bak commit 2a9b52785b94c45852276c4febb4e05d9e25de1f Author: nextflowertest <test@qq.com> Date: Wed Dec 2 22:16:59 2015 +0800 new data ty [root@flower1 committest]# get log --follow ready.txt.bak -bash: get: command not found [root@flower1 committest]# git log --follow ready.txt.bak commit 2a9b52785b94c45852276c4febb4e05d9e25de1f Author: nextflowertest <test@qq.com> Date: Wed Dec 2 22:16:59 2015 +0800 new data ty commit 1e5f4c75d4b1c6055fe68392fe0a431d9039870a Author: nextflowertest <test@qq.com> Date: Wed Dec 2 22:01:09 2015 +0800 yes [root@flower1 committest]# ls notyet.txt ready.txt.bak
七、追踪重命名注解:
略。
八、.gitignore文件:
这个文件中的内容可以比较灵活,格式如下:
- 空行会被忽略。以#开头的可以用于注释。
- 一个简单的字面值文件名匹配任何目录中的同名文件。
- 目录名由末尾的反斜杠/标记。
- 支持shell通配符。
- 起始的感叹号会对该行其余部分的模式进行取反。
当有多个层次的目录都有.gitignore文件时,优先级从高到低如下:
- 在命令行上指定的模式
- 从相同目录的.gitignore文件中读取的模式
- 上层目录中的模式
- 来自.git/info/exclude文件的模式
- 来自配置变量vore.excludedfile指定的文件中的模式
九、Git对象模型和文件的详细视图:
这一节主要通过几张图来说明各种变化。
下面这张图展示的是提交了2个文件的版本库视图。工作目录、索引以及对象库都是同步和一致的。
接着我们在工作目录里对file1进行编辑,现在它的内容包含“quux.”
然后使用git add命令,将file1内容提交到对象库中:
最后,执行git commit命令: