Git stash与常规commit的区别及相关技术疑问
Git Stash 相关疑问解答
1. Stash 和常规 git commit 提交的区别
- 存储内容维度不同:常规提交只保存暂存区(索引)的修改,对应文档里的
I提交;而stash是特殊的合并提交,同时保存工作区状态(W)和暂存区状态(I),通过双父节点关联当前HEAD(H)和暂存区提交。 - 历史可见性不同:常规提交会进入分支的历史记录,用
git log就能直接看到;stash不属于任何分支的历史链,默认git log不会显示,是独立的临时提交集合。 - 设计用途不同:常规提交用于记录代码的阶段性进展,是永久的历史节点(除非主动删除);stash是临时存储未完成的修改,方便切换分支、拉取代码时暂存当前工作,用完后通常可以丢弃。
- 提交结构不同:常规提交一般只有单个父节点(手动合并操作产生的提交除外);stash是固定的双父节点合并提交,结构为
W(工作区)以H(HEAD)和I(暂存区)为父节点。
2. 如何查看stash的哈希值
- 查看所有stash的完整哈希:执行
git stash list --pretty=format:"%H %s",输出会显示每个stash的完整哈希值和对应的描述。 - 查看单个stash的哈希:比如查看最新的stash,执行
git rev-parse stash@{0},把stash@{0}换成对应序号即可查看指定stash的完整哈希。 - 查看stash的提交结构和哈希:用
git log --graph stash,可以直观看到stash的提交树和哈希值。
3. 为什么stash必须是H与I的合并
stash的核心需求是完整保存当前工作的两个状态:暂存区的修改、工作区未暂存的修改。
H是创建stash时分支的最新提交,代表当前代码的基准状态;I是基于H生成的、记录暂存区状态的提交;W是记录工作区状态的提交。- 把
W作为H和I的合并提交,Git就能在恢复stash时,精准区分并还原暂存区和工作区的原始状态——比如用git stash apply --index可以恢复到创建stash时的暂存+工作区状态,而不是把所有修改都堆到工作区。如果只用单个提交,就没法区分这两个独立的状态了。
4. 这种合并为何不是快进式合并
快进合并的前提是:要合并的目标提交必须是当前分支HEAD的直接祖先(即目标提交在当前分支的历史链上,且没有新的提交产生)。
- 这里的
W是记录工作区状态的提交,它的内容和I(暂存区提交)、H(HEAD)都存在差异——工作区可能包含未暂存的修改,这些修改是I里没有的。 W既不是H的直接延续,也不是I的直接延续,不符合快进合并的条件,因此必须通过创建一个新的合并提交(W)来关联H和I,从而保存两个状态的差异信息。
内容的提问来源于stack exchange,提问作者Ooker
相关产品推荐
相关产品推荐

