我是一个自认为git重度运用的开发者,相关git课程买了2本,git官方教程终年保藏,其间 7.7节<<重置隐秘>>更是逐字研读,其他网上开源的git教程更是研读无数,但终究也只能当一个贮存代码的工具,碰上git diff、git diff –chache等指令,仍是搞不清,到底比对的是哪里的不同?

有没有跟我相同的,用了很长时间的git,也研究了好多次git,但终究仍是感觉哪里不对劲,仍是没有掌握把git说清。

这一次又在研究git,朝着git的山头又一次冲击,或许冲击的次数多了,量到了,这次恍然大悟了。

三大区域

git分三大区域。

作业区

作业区便是内容的寄存目录,你的任何代码操作都是在作业区进行。

暂存区

暂存区是寄存与作业区差异的地方。

commit(前史区)

其间commit比较特别,在许多材料里都没有明确的中文名,有的叫HEAD快照,有的叫commit,有的叫版本库,咱们权且叫前史区。

“修正”的误区

三大区的定义任何一本git材料上都能找到,上边仅仅简单介绍一下,其间对暂存区的介绍,或许任何人看了都要拿板砖拍我了,由于这种解说没有任何可了解性。这句话严厉意义上说是过错的。后边解惑。

看一下别的教程里的一些解说片段。

  • 第一步是用git add把文件添加进去,实际上便是把文件修正添加到暂存区;

  • 第二步是用git commit提交更改,实际上便是把暂存区的一切内容提交到当时分支。

  • add指令除了git add 文件名这种用法外,还能够运用add .来直接把作业目录下的一切改动悉数放进暂存区。

  • reset --soft会在重置HEADbranch时,保存作业目录和暂存区中的内容,并把重置HEAD所带来的新的差异放进暂存区。

这些解说都很标准,没有任何问题,注意这些定义中的”修正”和”差异”这些词,再看一下git status指令检查当时git状况。

git status的时分也会把这些差异显现出来。如下图:

git中被误解的概念

图中分别显现作业区修正的内容,暂存区修正的内容。

一切的材料,一切的运用协助都在告诉你个概念,作业目录放着你新的修正内容,暂存区放着与作业区的差异。

我一向以来也是这样了解的。

所以一向也搞不清”修正”的代码到底是啥东西,到底有啥规则。

直到我换了个思路了解。

作业目录放着悉数代码,不管新添加的仍是本来的,寄存着的便是悉数代码。

暂存区跟作业目录相同,也放着悉数代码,并不存在”修正”概念。

git status显现的仅仅一个增量状况,并不是作业区和暂存区实在的悉数代码。

每次你在作业区添加新代码时分,作业区寄存的代码便是你添加新代码后的悉数代码,git status中检查的状况是你增量的代码,他会用前史区的代码跟你作业区的代码进行比对,把差异显现出来。一起也会把暂存区的代码跟你作业区的代码进行比对,然后也把差异显现出来。

git add的时分是把你作业区的代码,提交到暂存区,由于暂存区有你改动前的代码,所以提交的代码能够了解为提交了一个”修正”,但不管怎么样终究暂存区的代码跟作业区的相同了,所以git status检查就看不出差异了。

了解 git diff

  • git diff
  • git diff –cached
  • git diff HEAD

曾经一向较劲脑汁想搞清这三个指令后显现的到底是谁跟谁的不同,可惜都未能成功,直到真的了解了暂存区和作业区。

  1. git diff 显现的是作业区悉数代码与暂存区悉数代码的差异。通过比对作业区和暂存区的代码,然后把差异进行显现。这里有的材料就说暂存区寄存着和作业区的”差异”。但这个差异很显然是在显现的时分,通过比对得出的结果,并不是把差异真的放在暂存区了。

  2. git diff –cached 显现的是暂存区悉数代码与前史区中的代码差异。有的材料说暂存区寄存着和前史区的差异,那你跟第一条指令放一块,假如没有了解到暂存区寄存着“悉数代码”这个概念,执着的盯着”差异”去了解这个指令,你会困惑”差异”为啥会变。暂存区一会寄存着和作业区的差异?一会寄存着和前史区的差异?很对立,很无解。

  3. git diff HEAD 显现的是作业区悉数代码与前史区代码进行比对,并显现差异。

一切的diff出来的差异都是通过比对后的结果,一切区寄存的是代码,并不是”差异”。

了解git reset

这个指令也是很让人困惑的指令,困惑后边跟着–soft –hard时分,作业区和暂存区到底有啥东西。

  1. git reset commitid

其他材猜中的解说:reset 不加参数:保存作业目录,并清空暂存区

这是某些材料里的解说,但其实实质是把指向的前史区代码放进了暂存区,而作业区代码没有任何改变。暂存区代码比作业区代码少了,出现了差异,一起暂存区与前史区代码相同,看着像是暂存区”差异”清空了。

  1. git reset –soft commitid

其他材猜中的解说: reset --soft会在重置HEADbranch时,保存作业目录和暂存区中的内容,并把重置HEAD所带来的新的差异放进暂存区。

这个指令的实质是作业区和暂存区寄存的一切的代码都没有任何变化,变化的是HEAD指向的commit从”当时”方位指向了指定方位。

由于作业目录和暂存区的代码彻底相同而又跟前史区的不相同,所以看着像是把”暂存区与前史区的差异”放进了暂存区。

  1. git reset –hard commitid

这个就更好解说了,把指定前史区的代码放在彻底放在作业区和暂存区,终究作业区,暂存区,前史区代码都相同,不存在差异

验证

以上所说的了解跟大部分材料都不相同,或许有人会怀疑,对我所说的暂存区寄存一切的是”悉数文件”而不是寄存差异有怀疑,说我这个概念是为了了解而杜撰出来的。

那你能够仔细阅读我之前说的git官方教程7.7节<<重置隐秘>>,里边会介绍一个git底层指令

git ls-files -s

能够检查当时暂存区的文件记载,这个记载是一个hash值,但满足表明暂存区到底是”清空”仍是有东西,假如git status查出来的暂存区状况为空,那用这个指令检查暂存区,假如有东西,那就证明,暂存区寄存的并不是”差异””修正”,而是”完好代码”。