git将每一次的提交都做一个快照,本次提交没有修改的文件就直接在新快照中建立对这个文件的索引,已经修改的文件则做一颗快照存下来。git pro上有一张图很好地解释了这个概念:
图片来自Pro Git
所以每次提交,git不会重复存储没有改变的文件,这使得磁盘空间的利用效率提高。从版本的角度来看,每个版本都能很清晰地隔开,回滚的时候不会有文件错位的情况。
既然说到版本了,我们来看一下git里面常用的几个关于版本控制的指令:
我们来看一下当前你都已经有了哪些提交:
git log 或者 git log -3
前面一条指令是查看所有的提交记录,后面一条指令是查看最近三次的提交记录。我本地的其中一条提交记录看起来是这个样子的:
commit 8b492e4d17abd3efb8f0aedb975738134c3aca68
Author: Casa Taloyum <casatwy@msn.com>
Date: Sat Feb 25 16:15:56 2012 +0800
removed the ajax to get deadline and added the casaHelper
这里面大家可能除了第一行不大熟悉,剩下三行应该一眼就知道是什么了。第一行的commit后面有一串hash,这个hash就是你的版本标识。比如说执行下面的指令:
git checkout 8b492e4d17abd3efb8f0aedb975738134c3aca68
那么你就会脱离库里面的所有分支,进入一个你当前没有分支的状态,然后你的工作目录上的所有文件的内容就全部回退到这一次版本下面了。这时候再使用checkout命令再切回你原来在的分支下面去,工作目录里面的文件又都回到最新状态了。你可以在执行这条指令之后新建一个分支,并且切换过去,那么新的分支里面的内容就是你切换到的版本的内容了。
这个一般用于回退到旧版本尝试开发新的补丁或者功能之类,或者你现在并不想彻底地将之前提交的记录撤销,而只是基于一个你想要去的旧版本进行一些修改的工作。
分支具体的事情你现在可以先不用去管,我会在下一篇文章里面说。
ok,git commit hash这条指令虽然能够使当前工作目录的文件回滚到你需要的版本,但是并不能直接进行开发,因为这条指令执行过后,你并不处于任何一个分支上面,你需要再新建分支并且提交,才能在这个旧版本上保存你的修改。如果要在当前分支上进行回滚,也是有一些指令能过做到这个的,我们来看一下:
git reset --hard 8b492e4d17abd3efb8f0aedb975738134c3aca68
此时旧版本就会回到8b492e4d17abd3efb8f0aedb975738134c3aca68这个时候,在这个版本以后的提交全部被删除,相当于没有修改过,没有提交过。一般来说这条指令是结合上面给出的git commit hash来使用的.
我们使用git commit hash来确认我们需要回滚到的版本号,然后checkout回来你的工作分支,然后执行git reset --hard 来彻底回滚过去。这里既然有hard,那么就有soft,就像这样:
git reset --soft hash
soft只是撤销那个版本号以及那个版本号之后的所有commit,并不会对你当前的工作目录里面的文件做任何修改,举个例子:
A-->B-->C
这三个是你的三次提交,你当前在版本C上面。你执行以下指令:
git reset --soft A
git commit -am "D"
那么此时就变成了:
A-->D
此时D版本的文件和C版本的文件完全一样,因为你没有对他做任何修改,只是撤销提交之后又重新提交了一次。比如说你commit时候的总结觉得想要换成别的,那么就可以用soft。
如果你commit了之后突然发现有些小的错误还需要修改,你当然可以用soft的方式回滚然后重新提交,当然,这里还有更加优雅的方法,当你修补之后提交的时,使用这样的指令:
git commit -C HEAD -a —amend
那么这次的commit就会复用上一次的信息,同时把你的修改补充进去,不额外地增加commit记录。
======================
如果现在是这样一种情况,你当前正在修改A,B,C文件,而你还没有提交,但是这时候你认为没有必要修改B文件,想要把你对B文件做出的修改撤销掉,返回到修改之前的样子,那么也可以使用git指令:
git checkout -- /home/casa/project/B
这样一来,你对B文件的修改就没有了,回到了修改之前的状态。顺便提供一个很有用的指令:
git status
这条指令告诉你当前git的状态,比如说你现在处在哪个分支,你修改了哪些文件,新建了哪些文件,以及分支合并时出现冲突的文件等等。上面给出的两条指令一般都是结合起来用比较好。