Git switch/checkout在索引与目标提交内容相同时的异常行为
Git分支切换的特殊行为解析
前置操作:创建本地测试仓库
git init echo foo > foo git add foo git commit -m foo git branch bar echo foo >> foo git commit -a -m 'another foo'
场景1:同时恢复暂存区与工作区到目标分支版本
执行命令将foo文件的暂存区和工作副本替换为bar分支的版本:
git restore --source bar --staged --worktree foo
随后执行分支切换:
git switch bar
预期行为
Git应因仓库处于dirty状态而拒绝执行switch操作
实际行为
Git成功完成切换,无任何异常提示。执行git status输出:
On branch bar nothing to commit, working tree clean
场景2:仅恢复暂存区到目标分支版本
执行命令仅将foo文件的暂存区恢复为bar分支的版本:
git restore --source bar --staged foo
再执行分支切换:
git switch bar
实际行为
Git仍允许切换分支,执行git status显示foo存在未提交修改:
On branch bar Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: foo
核心问题
- 为何Git会允许此次分支切换?
- 为何仓库处于dirty状态时,Git没有拒绝切换?
- 该行为背后的执行逻辑是什么?
- 哪里可以找到该行为的官方文档说明?
注:
git checkout也存在相同行为。
矛盾对比与疑问
Git官方文档中关于git switch的描述提到:
但若操作会导致本地修改丢失,将终止操作[...]
但这无法解释上述场景——如果执行以下未使用restore步骤的操作:
echo foo >> foo git add foo git switch bar
Git会正常拒绝切换,输出:
error: Your local changes to the following files would be overwritten by checkout: foo Please commit your changes or stash them before you switch branches. Aborting
理论上Git可以仅更新暂存区而不修改工作副本,从而避免丢失本地修改,但此时却拒绝切换;而当暂存区与目标分支内容一致时却允许切换,为何会存在这种例外情况?
内容的提问来源于stack exchange,提问作者Michi
相关产品推荐
相关产品推荐

