Git带着问题去实践(一)

之前翻译过一篇简短的《GIT CHEAT SHEET》,这里带着问题实践一下。

状态

在Git里文件有四种状态:untracked、unmodified、modified和staged。

第一个问题:untracked是什么状态?

touch一个README.md然后运行相关命令后有:

git01

在untracked状态下,README.md就像一个“路人甲”,没有被Git系统追踪。

第二个问题:如何查看modified状态下更改过的内容?

使用如下命令:

1
$ git diff README.md

第三个问题:如何查看进入staged状态后的内容?

使用如下命令:

1
$ diff --staged README.md

或者:

1
$ git diff --cached README.md

如果既有处于modified状态的内容,又有处于staged状态的内容,分别运行上文提到的命令,会得到什么结果?

编辑README.md文件内容:

1
2
3
4
5
First edit
staged状态
modified状态

其中第二行和第三行构造为staged状态,第四行和第五行构造为modified状态。

运行git diff命令有:

git02

运行git diff –staged / –cached命令有:

git03

从结果可以看出,modified状态对staged状态和unmodified状态一视同仁。而staged状态并未在乎modified状态的修改。

需要注意的是空行的修改。

staged状态怎么理解?

之前看过一些资料,有说法认为这是模仿这样一种功能:比如Windows上,当你要进行批处理操作时,在确定之前会给你一个勾选界面进行勾选。额,大概就是给你一个巴洛特利式思考人生的时间吧。

如果不需要思考人生,能不能跨过staged状态直接commit呢?

只要给commit添加参数 -a就可以了。

如何将README.md还原成untracked状态?

可以使用如下命令:

1
$ git rm --cached README.md

不能只使用rm,这样会出现“Changed but not updated:”(而且如果有内容处于modified状态或staged状态还要添加-f参数,这样做是为了保证安全),如果你希望保存文件夹下存在README.md,那么你也不仅仅要使用git rm,而应该添加–cached参数。

表格总结如下:

文件夹下保留文件 文件夹下不保留文件
Has _M git rm –cached git rm -f
Has M_ git rm –cached git rm -f
Has MM git rm –cached -f git rm -f
Not has MM git rm –cached git rm

现在来分析其中几个主要情况:

  • 文件包含modified状态的内容:

1.如果希望文件夹下保留文件,那么执行git rm --cached命令,然后查看状态:

git05

此时README.md处于untracked状态。

如何恢复到最开始文件包含modified状态的内容时的状态呢?首先执行git add README.md,然后再采用git reset HEAD README.md命令。或者,执行git reset HEAD README.md

2.如果希望文件夹下不保留文件,需要执行git rm -f,之所以要添加选项-f是为了数据的安全,当使用这个命令后,就意味着将舍弃modified状态和staged状态下的修改。

  • 文件夹下包含staged状态的内容:

基本和文件包含modified状态内容的情况相同,在恢复最开始内容的时候有点点出入。

  • 文件包含modified状态和staged状态的内容:

如果此时使用git rm --cached README.md命令会出现如下结果:

git06

所以要添加选项-f,想来也容易理解其中原因,当你要通过前述方法恢复数据的时候,你无法区分哪一部分是modified的内容,哪一部分是staged的内容,这就造成了信息丢失。

历史与撤销

如果仅仅是一次add犯了错,要还原成untracked状态还可以使用什么方法?

下面我们touch一个新的文件README02.md并add之,这个时候运行git status -s命令有:

git04

此时虽然README02.md的内容处于staged状态,但是它属于new file,所以用A表示。在这种情况下使用如下命令可将README02.md恢复到untracked状态:

1
$ git reset HEAD README02.md

能不能撤销README.md处于modified状态的修改?

可以,只需要使用如下命令:

1
$ git checkout -- README.md

如何查看最新提交的更新情况?

1
$ git show

如果要查看指定的某次提交更新的情况呢?

1
$ git show xxxx

xxxx对应git log打印出来的四十位SHA-1哈希码,可以把它当作每次commit的专属id。本人在本机上测试时,这个码至少要输入四位。

除此之外,还有方法查看最新提交的更新情况:

1
$ git log -p -1

经本人比较以上两条命令输出结果是一样的。该条命令中,-1如果改为-n,表示查看最近n条更新,省去查看全部更新。

如何比较某两次提交的变化?

使用如下命令:

1
$ git diff xxxx xxxx

两个参数xxxx对应要比较的两次提交id,谁作为第一个参数,谁就是参照物,最后的打印会显示以参照物为标准的变化。

如果git rm –cached README.md后,那么此时再add刚刚已经untracked的README.md后会发生什么呢?

实际上属于前文某表格下的分析的情形,但在那里的分析忽略掉了Not has MM的情况,这里进行说明。

如果当前的README.md既没有modified状态的内容,也没有staged状态的内容,在执行git rm –cached README.md后,继续add README.md,会出现如下结果:

git07

此时modified状态和staged状态下是没有内容的。

如何列出所有的SHA-1哈希码?

使用如下命令即可:

1
$ git reflog

小结

本篇用问答的形式,记录个人在使用Git上遇到的一些问题,下一篇将用同样的形式聚焦Git分支管理等功能。

参考

progit-zh-v2.1.1.pdf