经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » 编程经验 » 查看文章
使用plumbing命令来深入理解git add和git commit的工作原理
来源:cnblogs  作者:RivW  时间:2018/10/8 8:55:05  对本文有异议

前言: plumbing命令 和 porcelain命令

git中的命令分为plumbing命令和porcelain命令:

  • porcelain命令就是我们常用的git add,git commit等命令
  • plumbing命令可以理解为更底层的命令,实际上一个porcelain命令可以由若干个plumbing命令完成(见下文),plumbing命令可以帮助我们了解git底层的工作原理

阅读本文还需要了解.git目录的结构功能,以及git中的对象(commit对象、tree对象、blob对象等等)等概念,请自行参考其他文档。

1. git add

git add file在底层实际上完成了3个步骤:

  1. 根据文件内容计算SHA-1值
  2. 将文件内容存储到仓库的数据库中(.git/objects)
  3. 将文件内容注册到.git/index文件中

下面用plumbing命令完成git add的功能:

  1. ------------------------------------------------------------
  2. ~ ? git init demo
  3. Initialized empty Git repository in /home/lvhao/demo/.git/
  4. ------------------------------------------------------------
  5. ~ ? cd demo
  6. ------------------------------------------------------------
  7. ~/demo(master) ? echo "nihao" >> nihao.txt
  8. ------------------------------------------------------------
  9. ~/demo(master*) ? git status
  10. On branch master
  11. No commits yet
  12. Untracked files:
  13. (use "git add <file>..." to include in what will be committed)
  14. nihao.txt
  15. nothing added to commit but untracked files present (use "git add" to track)
  1. ~/demo(master*) ? git hash-object -w nihao.txt # 对应于步骤1和2,-w表示写
  2. ba9c1ad3d3b761e84cd8f9e9a18404f6f2552fcf

这时候查看.git/objects目录:

  1. ~/demo(master*) ? tree .git/objects
  2. .git/objects
  3. ├── ba
  4.    └── 9c1ad3d3b761e84cd8f9e9a18404f6f2552fcf
  5. ├── info
  6. └── pack
  7. 3 directories, 1 file
  1. ~/demo(master*) ? git update-index --add --info-only nihao.txt # 对应于步骤3(关于两个参数请参见git help update-index)

上面的update-index,就是更新.git/index文件,有关该文件的详细格式请参考https://stackoverflow.com/questions/4084921/what-does-the-git-index-contain-exactly。

该index文件主要包含了存在于暂存区(即index)中文件条目,可以通过git ls-files --stage来查看该文件的主要内容:

  1. ~/demo(master*) ? git ls-files --stage
  2. 100644 ba9c1ad3d3b761e84cd8f9e9a18404f6f2552fcf 0 nihao.txt

这时候,nihao.txt已经存在于暂存区(即index),所以说上面的三个步骤相当于git add nihao.txt

  1. ~/demo(master*) ? git status
  2. On branch master
  3. No commits yet
  4. Changes to be committed:
  5. (use "git rm --cached <file>..." to unstage)
  6. new file: nihao.txt

总结:

porcelain命令:

  1. git add file

等同于plumbing命令:

  1. git hash-object -w file
  2. git update-index --add --info-only file

2. git commit

commit所做的工作实际上是对当前的工作树(working tree)拍一个”快照“然后保存起来,git commit在底层实际上完成的步骤:

  1. 根据当前的工作树生成一个tree对象(tree对象记录了当前工作目录的结构,保存有对当前版本的文件的引用),将tree对象保存到.git/objects下
  2. 由上述tree对象生成一个commit对象,(可选)并指明该commit对象的parent、message等信息
  3. 移动分支到新生成的commit对象
  1. # 继续上面的代码
  2. ~/demo(master*) ? git write-tree # 即步骤1
  3. 8e335a3e0ffa15ff97acc7f4d97e03d63612ec7a

让我们查看一下这个tree对象,可见它保存了对当前工作目录下文件/目录的引用:

  1. ~/demo(master*) ? git cat-file -p 8e335a
  2. 100644 blob ba9c1ad3d3b761e84cd8f9e9a18404f6f2552fcf nihao.txt
  1. ~/demo(master*) ? git commit-tree -m "Initial Commit" 8e335a # 即步骤2
  2. 1f1fbcf8ff46d8d2548372c38cf3f1eabf8bfbc8 # 新生成的commit的SHA-1

这时候我们查看状态,还是待commit状态,这是因为commit-tree仅仅是生成了一个新的commit对象,并不会导致HEAD及分支的移动:

  1. ~/demo(master*) ? git status
  2. On branch master
  3. No commits yet
  4. Changes to be committed:
  5. (use "git rm --cached <file>..." to unstage)
  6. new file: nihao.txt

为了利用当前的分支,我们需要修改分支的引用,git update-ref refs/heads/分支名 commit-hash命令来更新分支的位置到刚刚创建的commit:

  1. ~/demo(master*) ? git update-ref refs/heads/master 1f1fbc # 即步骤3

由于.git/HEAD默认就是指向master分支,所以得到如下结果:

  1. ~/demo(master) ? git status
  2. On branch master
  3. nothing to commit, working tree clean

查看一下提交日志:

  1. ~/demo(master) ? git log --graph --oneline
  2. * 1f1fbcf (HEAD -> master) Initial Commit

总结:

porcelain命令的:

git commit -m "xxx" file

等同于plumbing命令的:

  1. git write-tree # 得到tree的hash: tree-hash
  2. git commit-tree -m "xxx" (-p parent-hash) tree-hash # 得到commit的hash,commit-hash
  3. git update-ref refs/heads/分支名 commit-hash
 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号