Git是一个分布式版本管理系统(我感觉类似于列族数据库Hbase,在Hbase中每次修改一个单元格,旧的内容不会被新修改的内容所覆盖,旧的内容和新的内容可以用不同的时间点访问得到),Git可以在任何时间点,把文档的状态作为更新记录保存起来。因此可以把编辑过的文档复原到以前的状态,也可以显示编辑前后的内容差异。
一、本地库的修改
每次添加或修改已添加文件时,想保存到本地数据库,就需要进行提交,提交后数据库会生成上次提交状态和当前状态的差异记录。
现在我们对sample.txt文件进行修改:
hello world //原来的内容
hello world! //修改后的内容,对比第一次多了一个感叹号
紧接着使用git status命令查看数据库情况:
它提示sample.txt文件被修改了,但是还没有提交。如果我们没有在修改之前和之后使用cat命令查看内容,就无法得知文件究竟修改了哪些地方。此时我们可以使用git diff命令查看究竟修改了哪些内容:
此时在进行提交,还是分成两步:先提交到索引,再提交。最后再查看一下本地库的状态。
git add sample.tx
tgit stauts
git commit -m "add mark"
git status
二、本地库的回退
1.git工作区、暂存区和本地库的基本概念
1.1工作区(working directory)
工作区就是我们本地的文件夹,比如这里/Users/qianying/learngit的learngit文件夹是我的工作区。
我们修改sample.txt的操作就是在工作区下操作的。
1.2暂存区(index or stage)
一般存放在 .git 目录下的 index 文件(.git/index)中,所以我们把暂存区有时也叫作索引(index)。
我们使用命令git add sample.txt将文件添加到暂存区。
1.3本地库(repository)
工作区有一个隐藏目录 .git,这个不算工作区,而是 Git 的本地库。
我们使用命令git commit -m "xxx"将暂存区中的内容提交到本地库。
1.4HEAD
用HEAD表示当前版本,上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100。
HEAD相当于一个指向不同版本的指针。
2.回退操作
上面我们学会了如何修改文件,并提交到本地库。接下来我们利用git的特性,把修改过的文件恢复到以前的状态。
现在我们再对sample.txt文件进行一次修改,并提交到本地库。那么三个版本的内容为:
hello world //版本
1hello world! //版本2,对比版本1多了一个感叹号
hello worold!hello qy //版本3,对比版本2添加了'hello qy'语句
我们可以使用git log命令查看本地库的历史记录,添加选项--pretty=oneline可以使输出内容更简洁
每一个记录前面的一大串字符串就是commit id(版本号),我们可以通过版本号将文件恢复到任何一个以前的状态。
使用git reset命令可以实现这个目的,它有三种选项:
–-mixed 重置HEAD和暂存区,默认参数,即相当于不带任何参数的git reset,保留工作区
–-soft 重置 HEAD,保留暂存区(或索引区)和工作区,让仓库恢复到执行git commit之前的状态
–-hard 重置HEAD,暂存区和工作区
2.1--hard
这里还没彻底了解这三个参数的含义,先用--hard试一下:
git reset --hard HEAD^
cat sample.txt
git log
git status
此时本地库的没有需要提交的文件。
使用命令git log后发现版本3不见了,如果想再次回到版本3,而且此时终端也没有关闭,就可以往上翻找版本3的版本号,然后使用版本号回到版本3,这里我的版本3的版本号是:180dcab564e6ffb124156d4aae35ff68fcbd36da。当然,版本号不用写全,git会自动取查找,但是也不能写太少。
git reset --hard 180dc
cat sample.txt
git log --pretty=oneline
git status
sample.txt文件内容变成版本3的内容,对应重置工作区;本地库的状态显示提交了两次,暂存区没有要提交的文件,对应重置暂存区。
带有选项--hard的git reset会彻底回退到某个版本,本地的文件也会变为上一个版本的内容 ,文件不会变成未add状态。索引(暂存区)内容和工作目录内容都会变给定提交时的状态。
2.2--soft
我们现在再试试选项--soft:
git reset --soft HEAD^
cat sample.txt
git log --pretty=oneline
git status
sample.txt文件内容并没有变化,还是版本3,对应保留工作区;历史记录也没有版本3,本地库的状态显示sample.txt被改变,对应保留暂存区。
带有选项--soft的git reset仅仅回退了commit的信息,本地文件的修改内容没有变,文件变为未commit状态(如果想要提交,直接commit即可)。索引(暂存区)和工作目录的内容是不变的,在三个命令中对现有版本库状态改动最小。
2.3--mixed
我们先恢复三个版本的状态,然后使用git reset --mixed HEAD^命令回到上一个版本:
git commit -m "add hello qy"
cat sample.txt
git log --pretty=oneline
git reset --mixed HEAD^
cat sample.txt
git status
工作区的内容没变,对应保留工作区;本地库状态显示sample.txt文件未被添加到暂存区,对应重置暂存区。
不带参数或者带有参数--mixed的参数git reset命令会回退到add之前的状态,本地文件修改的内容没有变,但是文件变为未add状态(如果想要提交,就需要add和commit命令)。
三、总结
本地库的文件被修改后,需要使用add命令现将工作区的文件交到暂存区,然后commit命令提交到本地库。
想要查看两次版本的不同,可以使用git diff命令。
想要历史记录更加简洁,就使用git log --pretty=oneline命令。
工作区、暂存区、本地库和HEAD的基本概念。
使用git reset命令进行回退操作,分析比较了三种参数的区别。--mixed是默认选项,--soft是三种选项中对本地库修改最小的,--hard是三种选项中对本地库修改最大的。