土法炼钢兴趣小组的算法知识备份

【Git 内部】日常 porcelain 命令改写了哪些文件

文章导航

分类入口
opensource
标签入口
#git#git-internals#porcelain#add#commit#checkout#reset

目录

学会 Git 命令不等于知道磁盘副作用。排查「提交后对象库没涨」「切换分支 index 乱了」,需要把 add / commit / branch / checkout / reset 映射到具体路径。本系列前几篇讲了 format;本篇把命令串起来。


一、总览

git add 到 git commit 的磁盘副作用链
各 porcelain 命令触达的 .git 路径矩阵

二、git add

git add <path>

  1. 读工作区文件,算 blob(或复用已有对象),可能objects/xx/… 松散对象。
  2. 更新 .git/index 对应条目(SHA、stat、stage=0)。

实测仅 git add f.txt 后(Git 2.54.0):

.git/index
.git/objects/78/981922613b2afb6025042ff6bd878ac1994e85

尚未写 refslogs


三、git commit

git commit

  1. 由 index 写 tree 对象(可能新建多级 tree)。
  2. commit 对象(含 tree、parent、author、message)。
  3. 更新 refs/heads/<当前分支> 为新 commit SHA。
  4. 追加 logs/HEADlogs/refs/heads/<branch>
  5. 刷新 index 与 HEAD tree 一致(通常)。

实测 git commit 后新增:

.git/logs/HEAD
.git/logs/refs/heads/master
.git/objects/2a/…  .git/objects/5f/…   # tree + commit(示例 SHA)
.git/refs/heads/master

blob 对象 78/… 与 add 时相同,被 commit 复用。


四、git branch

git branch <name> 创建 refs/heads/<name>,指向当前 HEAD commit;改 index、工作区、objects(除非配合 checkout)。

git branch -d 删除 refs/heads/<name> 文件;对象仍在,直至 gc prune。


五、git checkout(切换分支)

切换已有分支:

git checkout <commit> detached:HEAD 直接写 SHA。


六、git reset

模式 HEAD/ref index 工作区
--soft 移动 不变 不变
--mixed(默认) 移动 匹配新 HEAD 不变
--hard 移动 匹配新 HEAD 匹配新 HEAD

均写 reflog(reset:)。立即删除旧 commit 对象;若成为悬空,待 gc。

git reset 不删 objects/ 里已有 blob——历史提交中的文件内容仍可被其他 commit 引用。


七、对比快照方法

snapshot() { find .git -type f | sort > "/tmp/git-$1.list"; }
git add .
snapshot add
git commit -m 'c1'
snapshot commit
diff -u /tmp/git-add.list /tmp/git-commit.list

或用 find .git -newer .git/index 粗查最近改动(时间戳不可靠时应用快照 diff)。


八、本文边界


参考资料

系列索引Git 内部结构 · 上篇fsck · 下篇merge/rebase 文件

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。


By .