目录
为什么 commit 之前要先 add 一下呢?
我在刚接触 Git 命令的时候,对 Git 没什么概念,就是赶鸭子上线式的学习,用到什么,就去 Google 什么,例如第一天我搜索的就是“git first commit”,然后搜到很多 Git 的初级教程,几乎都有说先执行 git add ,然后 git commit。在我照着教程一步步 add & commit 的时候,我就在想,commit 就 commit唄,为什么 commit 之前必须要 add 一下呢?
当时才疏学浅,不敢胡乱尝试,担心试错了整不回来原来的样子。现在胆子大了些,决定尝试一下没有 add 的 commit。
通过 echo 命令给 master.txt 文件加了一行内容,然后执行提交:
测试结果很明显,commit 失败,失败原因是没有可以提交的修改,然而奇怪的是,查看 master.txt 文件,内容却已经添加成功。
好在 Git 非常贴心的给了我们详细的错误说明,下面仔细看一下:
On branch master
Changes not staged for commit:
modified: master.txt
no changes added to commit
英语渣的我最近热衷于翻译:
在 master 分支
修改没有被暂存起来以备提交
修改: master.txt
没有可以提交的修改
从这个提示信息中,我似乎嗅到了一丝丝的真(jian)相(qing),commit 时检测是否有修改的 master.txt,好像不是我看到的 master.txt。那我看到 master.txt 是什么?我没看到的又是什么?而且它在哪里?
答案就比较明显了,肯定在 Git 的暂存区(不然我为啥要举这个例子,哈哈)。
git commit 执行时,会提交暂存区的内容。git add 命令会将我们看到的修改添加到暂存区中,这就是为什么 git commit 之前要先执行 git add 的原因。
接着上面的问题,思维稍微发散一下,还可以问出很多问题,例如,add 将修改放入暂存区,那么 add 之前数据存放在哪里?commit 又将存储区的数据提交到什么地方了呢?以及为什么要这么分为几个存储部分?等看完这篇博客,希望你这些问题,都能找到答案。
Git 可以分为三个区
Git 本地数据管理,大概可以分为三个区,工作区,暂存区和版本库。
工作区(Working Directory)
是我们直接编辑的地方,例如 Android Studio 打开的项目,记事本打开的文本等,肉眼可见,直接操作。
暂存区(Stage 或 Index)
数据暂时存放的区域,可在工作区和版本库之间进行数据的友好交流。
版本库(commit History)
存放已经提交的数据,push 的时候,就是把这个区的数据 push 到远程仓库了。
下面是,当开发者通过 git 修改数据时,各区之间的数据传递流程示意图。
为了验证以上流程的正确性,我们可以自己动手实验一下,为了对比三个区之间的数据差别,过程中,可以借助神奇的 diff 命令。
命令 作用
git diff 工作区 vs 暂存区
git diff head 工作区 vs 版本库
git diff --cached 暂存区 vs 版本库
现在三个区的数据是一致的,执行 git diff 命令都为空
命令 接果
(工作区 vs 暂存区)git diff
(工作区 vs 版本库)git diff head
(暂存区 vs 版本库)git diff --cached
然后给 master.txt 添加一行内容后,现在工作区内容发生变化,暂存区和版本库内容不变。
命令 接果
(工作区 vs 暂存区)git diff
(工作区 vs 版本库)git diff head
(暂存区 vs 版本库)git diff --cached
执行git add 操作后,修改同步到暂存区,现在工作区和暂存区数据一致。
命令 接果
(工作区 vs 暂存区)git diff
(工作区 vs 版本库)git diff head
(暂存区 vs 版本库)git diff --cached
执行 git commit 操作后,修改已经同步到版本库,三区数据再次保持一致。
命令 接果
(工作区 vs 暂存区)git diff
(工作区 vs 版本库)git diff head
(暂存区 vs 版本库)git diff --cached
Stage 赋予 Git 更多灵活性
不知道时,你对它可能毫无所感。知道后,你一定会感动地想哭,并十分之膜拜 Git 的开发者- Linus Torvalds ,stage 就是这么精彩的玩意。以下看起来比较束手无策的场景,只要理解 stage,用好相应命令,都能轻易解决:
修改了4个文件,在不放弃任何修改的情况下,其中一个文件不想提交,如何操作?(没add : git add 已经add: git reset --soft )
修改到一半的文件,突然间不需要或者放弃修改了,怎么恢复未修改前文件? (git checkout)
代码写一半,被打断去做其他功能开发,未完成代码保存?(git stash)
代码写一半,发现忘记切换分支了?(git stash & git checkout)
代码需要回滚了?(git reset)
等等
上面提到的 checkout & stash & reset 等命令,通过不同的参数搭配使用,可以在工作区,暂存区和版本库之间,轻松进行数据的来回切换。
例如前篇 Branch 博客用到的 git reset 回滚命令,带上不同参数就有不同的作用,如下:
命令 作用
git reset --soft 暂存区->工作区
git reset --mixed 版本库->暂存区
git reset --hard 版本库->暂存区->工作区
完事大家可以自己新建一个测试 Demo,多尝试一下,相信你会因为暂存区的存在更加地喜欢 Git。