管理修改
下面的内容需要你掌握暂存区的知识,我就默认你已经完全掌握了暂存区的概念。现在我们要讨论的是,为什么Git比其他版本控制系统设计得优秀?因为Git跟踪并管理的是修改,而非文件。
为什么说Git管理的是修改,而不是文件呢?我们还是用小栗子说明一下。
1.对readme.txt做一个修改,比如加一行内容:
cat readme.txt
2.添加:
git add readme.txt
git status
3.再修改readme.txt:
cat readme.txt
4.提交:
git commit -m "git tracks changes"
5.提交后,再看看状态:
git status
到这里就会发现第二次的修改没有被提交。这是怎么回事啦?
让我们往回退一下看看前面的执行步骤:
第一次修改 -> git add -> 第二次修改 -> git commit
我们前面讲了,Git管理的是修改,当你用git add命令后,在工作区的第一次修改被放入暂存区准备提交,但是在工作区的第二次修改并没有被我们用git add命令放入暂存区,所以git commit只负责把暂存区的修改提交了,也就是第一次的修改被提交了,第二次的修改不会被提交。
提交后,用git diff HEAD – readme.txt命令可以查看工作区和版本库里面最新版本的区别:
git diff HEAD -- readme.txt
从这里可以看出第二次修改确实没有被提交。
那怎么提交第二次修改呢?你可以继续git add再git commit,也可以别着急提交第一次修改,先git add第二次修改,再git commit,就相当于把两次修改合并后一块提交了:
第一次修改 -> git add -> 第二次修改 -> git add -> git commit
现在你应该理解了Git是如何跟踪修改的,每次修改,如果不add到暂存区,那就不会加入到commit中。
撤销修改
我们往往会碰到一种情况就是修改完了之后才发现刚刚修改的地点被改错了,既然错误发现得很及时,就可以很容易地纠正它。比如我们刚刚在最后添加的哪一行错了,你可以删掉最后一行,手动把文件恢复到上一个版本的状态。如果用git status查看一下:
git status
Git会告诉我们,用git checkout – file可以丢弃工作区的修改:
git checkout -- readme.txt
命令git checkout – readme.txt意思就是,把readme.txt文件在工作区的修改全部撤销,这里有两种情况:
一种是readme.txt自修改后还没有被放到暂存区,撤销修改就回到和版本库一模一样的状态;
一种是readme.txt已经添加到暂存区后,又作了修改,撤销修改就回到添加到暂存区后的状态。
总之,就是让这个文件回到最近一次git commit或git add时的状态。现在,看看readme.txt的文件内容:
cat readme.txt
文件内容果然复原了。
需要注意的是 git checkout – file命令中的–,没有–,就变成了“切换到另一个分支”的命令,我们在后面的分支管理中会再次遇到git checkout命令
现在假定是凌晨3点,你不但写了一些胡话,还git add到暂存区了:
cat readme.txt
git add readme.txt
庆幸的是,在commit之前,你发现了这个问题。用git status查看一下,修改只是添加到了暂存区,还没有提交:
git status
Git同样可以帮你搞定,用命令git reset HEAD file可以把暂存区的修改撤销掉(unstage),重新放回工作区:
git reset HEAD readme.txt
git reset命令既可以回退版本,也可以把暂存区的修改回退到工作区。当我们用HEAD时,表示最新的版本。
再用git status查看一下,现在暂存区是干净的,工作区有修改:
git status
还记得如何丢弃工作区的修改吗?
git checkout -- readme.txt
git status
这个时候也许可以睡一个安稳觉了,我是不是应该说句晚安啦。
不过,假设你不但改错了东西,还从暂存区提交到了版本库,怎么办呢?还记得版本回退一节吗?可以回退到上一个版本。不过,这是有条件的,就是你还没有把自己的本地版本库推送到远程。还记得Git是分布式版本控制系统吗?我们后面会讲到远程版本库,一旦你把“stupid boss”提交推送到远程版本库,你就真的惨了
删除文件
在Git中,删除也是一个修改操作,我们通过一个小栗子来玩一把。先添加一个新文件test.txt到Git并且提交:
git add test.txt
git commit -m "add test.txt"
一般情况下,你通常直接在文件管理器中把没用的文件删了,或者用rm命令删了:
rm test.txt
这个时候,Git知道你删除了文件,工作区和版本库就不一致了, git status命令会立刻告诉你哪些文件被删除了:
git status
现在你有两个选择,一是确实要从版本库中删除该文件,那就用命令git rm删掉,并且git commit:
git rm test.txt
git commit -m "remove test.txt"
现在,文件就从版本库中被删除了。
命令git rm用于删除一个文件。如果一个文件已经被提交到版本库,那么你永远不用担心误删,但是要小心,你只能恢复文件到最新版本,你会丢失最近一次提交后你修改的内容。
另一种情况是删错了,因为版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本:
git checkout -- test.txt
git checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。