从提交K新建Git分支为何缺失我的C-J提交?技术咨询
为什么从提交K新建分支会缺失C-J的提交?
问题场景
我在某分支上完成了A、B、C、D、E、F、G、H、I、J提交,同事从我的B提交拉出分支开发,本周他将提交合并到我的分支。我执行git pull同步后,分支上新增了提交K(普通提交)和L(合并提交),却发现C-J提交对应的代码被全部回退。
我怀疑合并提交L是问题根源,但不会回退合并提交,于是尝试从提交K新建分支,却发现该分支仅包含A、B、K提交,缺失C-J。删除该分支后,我从提交J新建分支,成功恢复了A到J的所有提交。
我的问题是:为何从提交K新建分支时,我的C-J提交不会显示?提交K看起来是普通提交而非合并提交。
原因解析
核心问题是提交K的父提交链里根本没有C-J,具体逻辑如下:
- 同事从B拉分支开发后,合并时大概率用了
git rebase改写历史,或者直接强制推送覆盖了远程分支的原有历史。原本你的分支历史是A → B → C → D → … → J,但同事操作后,远程分支的历史变成了A → B → [同事的提交] → K,你的C-J提交被挤出了远程分支的主线,变成了游离的孤立提交。 - 你执行
git pull时,如果Git检测到远程分支历史和本地不一致(被改写),会根据你的pull配置处理:- 若配置了
pull.rebase=true,Git会把本地的C-J提交暂存,直接拉取远程的新历史(A→B→同事提交→K),再尝试把C-J变基到K上——但如果变基失败,可能就会生成合并提交L,此时K的父链还是B→同事提交,和C-J无关。 - 若用默认的merge拉取,Git会把远程的新历史和本地历史合并,生成合并提交L,但K本身属于远程的新历史链,父节点是同事的最后一个提交,而同事提交的父节点是B,所以K的上游链里没有C-J。
- 若配置了
- Git的分支本质是指向某个提交的指针,从K新建分支时,只会包含K及其所有上游父提交(也就是A、B、同事提交、K),而C-J是和这条链完全独立的历史,自然不会出现在这个分支里。
- 而从J新建分支时,J的上游链是完整的
A→B→C→…→J,所以能包含所有这些提交。
验证方式
你可以用以下命令查看提交链,确认K的父节点:
git log --oneline --graph K
执行后会看到K的提交链是A → B → [同事提交] → K,完全不包含C-J;而查看J的提交链:
git log --oneline --graph J
会显示A → B → C → D → … → J的完整连续历史。
内容的提问来源于stack exchange,提问作者Ray
相关产品推荐
相关产品推荐

