一、工作区和暂存区
Git和其他版本控制系统的不同之处就是有暂存区的概念。暂存区是Git非常重要的概念,弄明白了暂存区,就弄明白了Git的很多操作到底干了什么。
前面讲了向Git版本库里提交文件分两步执行:
- 用
git add 把文件添加进去,实际上就是把文件修改添加到暂存区; - 用
git commit 提交更改,实际上就是把暂存区的内容提交到当前分支。
简单理解为,需要提交的文件修改全部放到暂存区,然后,一次性提交暂存区的所有修改。因为我们创建Git版本库时,Git自动为我们创建了一个master 分支,所以git commit 就是往master 分支上提交更改。
下面开始实战,先对 readme.txt 加上一行内容,然后再新建一个LICENSE 文本文件。
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.
先用git status 查看一下状态:
$ git status
On branch master
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: readme.txt
Untracked files:
(use "git add <file>..." to include in what will be committed)
LICENSE
no changes added to commit (use "git add" and/or "git commit -a")
Git告诉我们 readme.txt 被修改了,而 LICENSE 还从来没有被添加过,所以它的状态是Untracked 。
现在把readme.txt 和LICENSE 都添加后,再查看一下状态:
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: LICENSE
modified: readme.txt
现在,暂存区的状态就变成这样了:
所以,git add 命令就是把要提交的修改放到暂存区(Stage),然后执行git commit 就可以一次性把暂存区的所有修改提交到分支。提交后如果没有对工作区做任何修改,那么工作区就是“干净”的。
$ git status
On branch master
nothing to commit, working tree clean
现在版本库变成了这样,暂存区就没有任何内容了:
二、管理修改
在Git中是对修改进行跟踪并管理,而非文件。比如新增或删除了一行,更改了某些字符,甚至创建一个新文件,这都算是修改,都会被Git跟踪并管理。下面通过实验来说明。
第一步,为 readme.txt 加一行内容:
$ cat readme.txt
Git is a distributed version control system.
Git tracks changes.
然后添加到暂存区:
$ git add readme.txt
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: readme.txt
然后再修改 readme.txt:
$ cat readme.txt
Git is a distributed version control system.
Git tracks changes of files.
提交:
$ git commit -m "git tracks changes"
[master 519219b] git tracks changes
1 file changed, 1 insertion(+)
提交后,再看看状态:
$ git status
On branch master
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: readme.txt
no changes added to commit (use "git add" and/or "git commit -a")
会发现第一次修改被提交了,而第二次的修改没有被提交。这是因为Git管理的是修改,当你用git add 命令后,在工作区的第一次修改被放入暂存区,准备提交,但是第二次修改并没有放入暂存区,所以,git commit 只负责把暂存区的修改提交了。
三、撤销修改
假如你在readme.txt 中添加了一行内容,在提交前你又删掉这一行内容,手动把文件恢复到上一个版本的状态。用git status 查看一下:
$ git status
On branch master
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: readme.txt
no changes added to commit (use "git add" and/or "git commit -a")
可以发现Git会告诉你,git checkout -- file 可以丢弃工作区的修改:
$ git checkout -- readme.txt
命令git checkout -- readme.txt 意思就是,把 readme.txt 文件在工作区的修改全部撤销,这里有两种情况:
-
readme.txt 自修改后还没有被放到暂存区,现在撤销修改就回到和版本库一模一样的状态; -
readme.txt 已经添加到暂存区后,又作了修改,现在撤销修改就回到添加到暂存区后的状态。
总之就是让文件回到最近一次git commit 或git add 时的状态。
git checkout -- file 命令中的 -- 很重要,没有-- ,就变成了 “切换分支” 的命令。
假如已经把错误代码git add 到暂存区了,但在commit 之前发现了这个问题。用git status 查看一下,修改只是添加到了暂存区,还没有提交:
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: readme.txt
Git告诉我们,用命令git reset HEAD <file> 可以把暂存区的修改撤销掉(unstage),重新放回工作区:
$ git reset HEAD readme.txt
Unstaged changes after reset:
M readme.txt
git reset 命令既可以回退版本,也可以把暂存区的修改回退到工作区。当我们用HEAD 时,表示最新的版本。
查看一下状态,现在暂存区是干净的,工作区有修改:
$ git status
On branch master
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: readme.txt
四、删除文件
在Git中删除也算修改操作,例如新建一个文件test.txt 并提交:
$ git add test.txt
$ git commit -m "add test.txt"
[master b84166e] add test.txt
1 file changed, 1 insertion(+)
create mode 100644 test.txt
然后再把 test.txt 文件删除,这个时候,Git知道你删除了文件,因此,工作区和版本库就不一致了,使用git status 命令查看哪些文件被删除了:
$ git status
On branch master
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
deleted: test.txt
no changes added to commit (use "git add" and/or "git commit -a")
现在你有两个选择,一是确实要从版本库中删除该文件,那就用命令git rm 删掉,并且git commit :
$ git rm test.txt
rm 'test.txt'
$ git commit -m "remove test.txt"
[master d46f35e] remove test.txt
1 file changed, 1 deletion(-)
delete mode 100644 test.txt
现在,文件就从版本库中被删除了。
先手动删除文件,然后使用git rm <file> 和 git add<file> 效果是一样的。
另一种情况就是误删了,但是版本库里还存有该文件,可以用git checkout 命令把误删的文件恢复到最新版本。
$ git checkout -- test.txt
五、总结
-
每次修改,如果不用git add 到暂存区,那就不会加入到commit 中。 -
当改乱了某个文件的内容,想丢弃工作区的修改时,用命令git checkout -- file 。 -
当改乱了某个文件的内容并添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD <file> ,就回到了场景1,第二步按场景1操作。 -
假设把错的文件从暂存区提交到了版本库,想要撤销本次提交,只能进行版本回退。 -
命令git rm 用于删除版本库里的文件。如果不小心误删了,但是文件已经提交到版本库,那么就可以从版本库将文件进行还原,但是只能恢复文件到最新版本,你会丢失最近一次提交后你修改的内容。
感谢大家的耐心阅读,如有建议请私信或评论留言
|