Git未提交修改排查全攻略:status、diff与提示词固化技巧

📅 发布时间:2026/10/5 7:23:57
Git未提交修改排查全攻略:status、diff与提示词固化技巧
手头的Kiro项目连着改了两天结果一打开终端面对一屏git status输出我愣是说不清楚自己到底改了哪些文件、每个文件动了哪几行。这种状态太典型了——不是不会敲命令而是没有一个固定的检查套路。后来我做了一套属于自己的提示词prompt把查看未提交的修改这一步从凭感觉变成了流水线式排查效率提上来一大截。这篇文章就把这套思路整个拆开git里未提交的修改到底藏在哪里、三条diff命令分别看什么、怎么把检查动作做成一份可以复制进AI工具的prompt以及提交前、合并前、评审前怎么快速把改动看明白。新手能直接照着敲老手也能从提示词固化和场景化使用里捞到点新东西。1. 先把手头这张未提交的地图看清楚很多人一提到查看未提交的修改第一反应就是git status。没错status是入口但它只是告诉你有变化细节还得靠后面的命令。想要真正把改动看明白得先搞懂Git把未提交这三个字拆成了几种状态。1.1 工作区、暂存区、本地仓库三个格子别搞混Git的日常操作可以简化成三个区域工作区、暂存区、本地仓库。工作区是你电脑上真实可见的文件夹你在这里改代码暂存区是一块过渡区域相当于准备打包的货架你把想提交的改动先用git add放上去本地仓库是已经提交过的历史存档。这样看的话未提交的修改其实存在两种位置还在工作区里没被git add的和已经git add进暂存区但还没git commit的。这两类改动性质不同前者是我才改完还没决定要不要交后者是我已经明确这部分改动要进入版本历史。很多误操作都出在这里——比如直接git checkout .它只会把工作区没暂存的改动扔掉并不动暂存区反过来git reset又能把暂存的东西打回工作区。分不清这两个地方后面所有排查都是瞎猜。另外还有一种特殊情况本地仓库里已经有一个新提交但这个提交还没推到远程。严格说它不算未提交的修改但在日常交流里经常会被一起问起来所以排查的时候我也会顺手看一眼git log确认本地领先了远程几个commit。1.2 三种未提交场景用一个status全部摊开在Kiro项目里我习惯先跑git status它的输出会把三种场景一次性摆出来。第一种Changes not staged for commit这类文件有改动但还没被git add进暂存区。输出里文件名前面有个红色终端默认配色提示这堆东西还漂在工作区。第二种Changes to be committed文件已经git add过了等着git commit。输出里文件名前面的状态字母是绿色表示已经在货架上。第三种比较隐蔽同一个文件既出现在to be committed又出现在not staged里——这说明你对一个已暂存的文件又做了新修改。举个例子我先改了config.js并git add进去然后又改了它一次第二次改动还在工作区。这时候git status里会两次提到config.js分别对应暂存区里的旧版本和工作区里的新改动。如果直接git commit提交进去的其实是暂存区里的旧版本第二次改动会被落在后面。所以我的习惯是git status之后先用眼睛扫一遍三类内容的数量。如果某个文件同时出现在两个分类下先停下来想清楚哪个版本才是我要提交的。1.3 让status输出更清爽的小技巧标准的git status很啰嗦它会把下一步操作的提示也一起打出来。看多了会觉得吵我常用的是git status -s或者git status --short。这个命令的输出一行一个文件左边两位是状态码第一位表示暂存区的状态第二位表示工作区的状态。比如M表示已暂存但无额外工作区改动M表示工作区改了但没暂存MM表示暂存区和工作区都有改动??表示未跟踪的新文件。这套短输出好处是可以一眼扫完整个项目的改动面。我在Kiro项目里做每日自检时都会先git status -s再看有没有??出现——未跟踪的新文件经常是忘记加入版本控制的临时脚本、日志文件漏掉了很麻烦。另外还可以配合git status --ignored看一眼被忽略的文件确认.gitignore配置没把重要文件误伤。2. diff家族把每一行改动都摊在桌上status只是地图告诉你哪里动了diff才是放大镜告诉你每一行具体变成了什么。很多人在这一步卡住是因为不知道三个diff命令分别看什么随手敲一个git diff看不到预期的内容就开始怀疑人生。2.1 三个diff命令的边界先从最简单的区分说起git diff比较工作区和暂存区。换句话说看的是还没add的改动。git diff --cached等价于git diff --staged比较暂存区和本地仓库最后一个commit。看的是已经add但还没commit的改动。git diff HEAD比较工作区和本地仓库最后一个commit。把上面两段加起来一次性看所有未提交的改动暂存未暂存。用Kiro项目举个例子。假设我改了README.mdgit add之后又动了它一次此时git diff只显示第二次改动git diff --cached只显示第一次改动git diff HEAD显示全部改动。实践里最常用的是git diff因为工作中大量时间花在我刚刚改了东西想看看到底改了什么这个场景。git diff --cached则在提交前做最后审查时用确认即将进入版本历史的改动是否正确。git diff HEAD适合在一大轮修改之后把所有家底一次翻出来看。2.2 diff输出到底在说什么很多新手面对diff输出会发懵其实格式非常机械。拿一个Kiro项目里实际的片段来说明diff --git a/src/config.js b/src/config.js index 8d3f1a2..e4b5f7c 100644 --- a/src/config.js b/src/config.js -15,7 15,7 const apiBaseUrl process.env.API_BASE_URL第一行是文件对比头a/代表旧版本b/代表新版本。第二行是文件索引信息平时基本用不到。第三行和第四行的---与表示旧的叫a版本新的叫b版本。正文里以-开头的行是删掉的内容以开头的行是新增的内容前面带空格的行是没变的上下文。 -15,7 15,7 是个定位标记表示旧文件从第15行开始、连续7行新文件也从第15行开始、连续7行后面还跟一个小片段提示附近是什么函数或上下文。看diff有个技巧别逐行读重点看标记它能告诉你改动发生在哪个函数、哪个区域。我之前排查Kiro项目一个问题时就是靠发现改动其实落在错误处理函数里而不是我以为的请求封装函数省了大半天。2.3 高频变体参数diff默认输出完整上下文改动很大时终端能刷好几屏。我常用的几个参数都是为了让输出更可控git diff --stat只显示每个文件增删了多少行一楼目录结构。适合快速把握这次修改涉及范围。git diff --name-only只显示文件名不显示具体改动适合我只需知道改了哪些文件。git diff --name-status文件名加状态字母比如M表示修改、A表示新增、D表示删除非常直观。git diff --word-diff按单词粒度比较。代码里那种只改了一个变量名的场景默认diff会显示整行被删又被加用--word-diff可以精确定位到变化的单词。git diff --check检查是否存在空白字符错误比如行尾多余空格、文件末尾没有换行符。这个在提交前跑一下很有用。这些参数都适用于--cached组合起来比如git diff --cached --stat就是看暂存区里即将提交的改动规模。把它们记成固定组合排查效率会高很多。2.4 实战Kiro项目一次改动排查举一个实际的排查过程。那是在Kiro项目里改登录模块我先改了src/api/auth.js里两个接口的请求参数又改了src/store/user.js里的状态处理逻辑中间顺手往README.md里加了一行使用说明。这三个文件的状态不一样README改完就add了auth.js改完没adduser.js则是add过一次又改了一次。我先git status -s确认状态输出是M README.md M src/api/auth.js MM src/store/user.js于是排查动作就清晰了看暂存区的完整改动git diff --cached重点审README和user.js的第一次改动看工作区的新改动git diff重点审auth.js和user.js的第二次改动如果要全量过一遍就git diff HEAD --stat。这一套下来我不仅知道改了什么还知道每部分的身份——哪些是准备提交的、哪些还悬而未决。关键是把步骤固定下来形成肌肉记忆。3. 把查改动变成一套提示词prompt讲到这里你可能会觉得命令都会了但每次检查还是要花不少心力。这就轮到标题里那个提示词prompt出场了。我这里说的prompt不只是给AI的那段对话模板它更像一套检查话术——你把自己要做的事、要看的范围、要的输出格式写成一段话然后固化下来每次照章执行。3.1 提示词不只是给AI的接触AI辅助编程的人对prompt很熟但提示词的思路完全可以反过来用在自己身上。比如我给自己定的未提交修改检查提示词是看到任何代码改动先看status确定范围再看diff看内容最后看log确认上下文。这三步对应三句话改了什么具体怎么改的在哪个历史背景下改的这套话术用代码固化下来就是一组git别名。我建议不要背命令直接把高频操作固化成简短别名我本人的~/.gitconfig里有这么几行[alias] st status -s df diff dfc diff --cached dfh diff HEAD dfst diff --stat dfw diff --word-diff chk diff --check配置之后git st、git dfc、git dfst一敲就走把记忆负担降到最低。新同事看我的终端总问这些缩写是什么我说这就是我那套提示词——每次检查都用一个固定的、一致的动作入口不容易漏。3.2 一段可直接复制的AI提示词模板如果你用AI工具比如各类代码助手的对话窗口帮你审查diff那段提示词就更重要了。我把自己用了很久的一个模板贴出来你可以直接复制修改我现在有一个使用Git管理的项目需要你帮我审查未提交的修改。 我会先给你几段diff输出包括git diff和git diff --cached的结果请你按以下顺序分析 1. 先用几句话概括全部改动涉及的功能模块和文件范围。 2. 逐个文件说明改动意图重点标注可能导致问题的点变量命名不一致、逻辑分支遗漏、异常没有处理、格式与项目风格不符。 3. 提醒我是否有提交前需要补做的事是否缺少测试、是否有调试代码、是否包含敏感信息、是否有未删除的注释。 4. 如果改动会影响到已有函数的外部调用请特别标出。 5. 最后给出一个推荐的commit message按Conventional Commits风格。 注意如果diff内容里包含密钥、token、个人隐私信息请直接提醒我脱敏不要展开分析内容本身。这段prompt的核心在于它把审核diff这个模糊任务拆成了明确的五个输出项。我实际用过几次后发现AI能比我肉眼更快发现某个改动只改了调用方却忘了改函数定义这种容易被忽略的连带问题。但有个前提给的diff要完整最好把git diff HEAD的输出全量贴进去只给--stat结果的话AI只能猜。3.3 用alias固化你的本地提示词如果你的AI工具支持命令行调用或者你平时用shell脚本比较多可以更进一步把上面那段prompt保存成文件比如~/prompts/diff_review.md然后写一个简单的shell函数把当前仓库的diff输出自动拼上prompt模板一键生成一条完整请求。一个最简单的版本是这样在~/.bashrc或~/.zshrc里加入git-diff-review() { { cat ~/prompts/diff_review.md echo ----- diff output start ----- git diff HEAD echo ----- diff output end ----- } }想组合AI工具的时候把git-diff-review的输出传给AI即可。我在Kiro项目里还试过在函数里自动拼接git status -s和git log --oneline -5让AI不仅能看当前改动还能知道最近提交的上下文分析结果会准确很多。这个提示词体系的好处是审查标准固定了不会因为某天状态不好就漏掉关键检查项。3.4 外部AI的diff审核注意点用外部AI服务处理diff时要小心两件事。第一是数据安全代码片段属于公司的内部资产直接把整段diff贴到公共平台存在泄露风险。我的做法是脱敏后再贴把函数名、变量名换成a、b、c只保留逻辑结构或者只贴有问题的那几行而不是全量输出。第二是提示词本身也可能被内容安全机制拦截有时候你贴的代码里包含了某些被系统误判的字符串AI平台会返回类似invalid prompt的报错意思是当前请求被视为违规。这种情况不代表你的代码有问题换个描述方式、去掉敏感词再试就行。我遇到过几次之后现在习惯把diff内容里明显的内部项目名、真实账号信息先替换掉再进AI。4. 三个高频场景里未提交修改怎么用才不出事命令和提示词都备齐了最后要看的是场景。同样一条git diff在提交前、合并前、评审前用的是三种完全不同的姿势。下面是我踩过坑之后总结的用法。4.1 提交前五分钟自查流水线我总结的提交前自查顺序是固定的每一步有明确目的。先把git st跑一遍摸清范围再跑git chk检查空白符问题然后git dfst看改动规模确认没有误夹带无关文件比如编译产物、日志接着git dfc审查即将进入暂存区的所有改动确认无误后git commit。这里有个容易被忽视的细节如果某个文件是MM状态说明暂存区里的版本不是最新改的提交前必须重新git add否则你会把旧的、不完整的版本提交进去。我见过不止一个人在这里翻车提交完才发现某一行改动根本没进去只能再打一个fix补丁提交历史变得很啰嗦。如果文件已经add了但有新改动实际操作是git add该文件然后git dfc再看一遍。习惯上我把重新add再审查当成一个不可跳过的动作。4.2 切换分支/合并前给未提交修改找一个安全的家在Kiro项目里我经常改到一半被叫去修一个线上问题需要马上切换分支。这时候最危险的指令是带着未提交修改直接git checkout如果两个分支之间同一文件内容不同Git会拒绝切换拒绝理由里会提到your local changes would be overwritten。如果内容相同切换会成功但改没来的既可能被带过去容易搞混。处理方式是用git stash把未提交修改暂时存起来。基本流程git stash save 登录模块改动中途确认git status干净之后切换分支处理完回到原分支再git stash pop恢复。这里有个关键点git stash默认只会stash已跟踪文件的改动新添加的未跟踪文件不会被带走需要加-u参数git stash -u连未跟踪文件一起保存。如果忽略这一点切完分支回来发现新写的文件还躺在工作区可能直接污染另一个分支的提交范围。另外git stash pop有冲突的可能恢复时如果当前工作区和stash的改动撞了Git会停下来让手动解决。所以我恢复stash时习惯先git status -s看清楚再pop避免冲突之后一地鸡毛。4.3 评审前把改动压到最小、讲得最清楚代码评审时评审人最怕的是看到一坨混装的改动——这个文件只是改个变量名那个文件加了新逻辑全都藏在一次提交里。虽然这属于提交粒度问题但在评审前同样可以靠diff来补救。如果同一批改动还没提交我建议用git diff --name-status先列出文件清单再按文件类型分批展示纯格式化/重命名的放一组核心逻辑改动放一组测试代码放一组。这样评审者可以先看重点再扫次要部分。如果改动涉及很多文件git diff --stat是个很好的开场白能让评审者一分钟内知道整个PR的规模。还有一个实用技巧用git diff配合--function-context参数部分版本支持让diff显示改动所在的函数名比默认的上下文更容易定位逻辑边界。我在Kiro项目的代码评审中经常用这一手评审者反馈说能更快知道这个改动属于哪个模块了。5. 常见问题与排查技巧实录工具和方法归齐了真正干活时还是会遇到各种意外。下面这些是我在真实项目里帮你趟过的坑按现象—原因—解法给出。5.1 为什么git diff空空如也最常被问到的就是我明明改了文件为什么git diff什么都不显示先别慌按顺序查三件事。第一个原因改动已经在暂存区里此时git diff默认不显示已暂存内容换成git diff --cached或git diff HEAD看。第二个原因改了但没保存在IDE里没触发文件保存这不算是Git的问题重新保存再跑。第三个原因更隐蔽文件是未跟踪的新文件??状态下diff默认是忽略的需要先git add再git diff --cached或者直接用git diff --no-index /dev/null 新文件看内容。这三种都不会报错所以排查起来要靠从状态反推命令。另外如果你在一个子目录里执行git diff它只会显示当前目录下的改动。想一次看完整仓库把命令在仓库根目录跑或者用git -C /path/to/repo diff指定仓库路径。5.2 误覆盖、误删除后的恢复路径有一次我在Kiro项目里想放弃某个文件的改动直接敲了git checkout -- src/config.js然后猛然想起来这个文件里还有一小段我不想丢的调试逻辑没备份。git checkout --会把工作区的改动直接覆盖掉而且是不可恢复的——除非改动之前已经git add过。这里提醒一下如果改动已经进过暂存区被覆盖后可以用git fsck --lost-found去找悬挂的blob对象有一定概率捞回来但过程很折腾。所以更稳妥的做法是任何可能想反悔的改动先git stash save 备份再决定要不要真的丢弃。git stash相当于给改动买个保险恢复成本极低。新版Git推荐用git restore替代git checkout --语义更清晰git restore file丢弃工作区改动git restore --staged file把暂存区的状态退回工作区。我建议新项目里统一用git restore团队沟通时少很多歧义。5.3 远程认证失败未提交修改怎么保护远程操作时出现SSH认证失败或push被拒很多人的第一反应是反复重试这个动作很危险——尤其是当你本地有未提交修改时被拒之后人在焦虑状态下容易乱敲命令把本地改动弄丢。遇到认证失败先做三件事备份当前状态、确认认证配置、再尝试推送。备份当前状态就是git status -s确认哪些文件改动着如果有重要改动先git stash -u存一波绝不能带着半成品去处理远程问题。然后检查SSH的key是否加载进ssh-agentssh-add -l看一下如果显示没有key就ssh-add ~/.ssh/id_ed25519同时确认远程地址是SSH格式还是HTTPS格式git remote -v看一眼两者用的认证方式完全不同。HTTPS地址的认证问题一般是账号密码或token失效SSH地址则看公钥是否已注册到托管平台。等远程操作恢复正常后git pull完再git stash pop恢复未提交改动。5.4 IDE里的对照组IDEA Local Changes与VS Code命令行之外IDE里的视图也很常用关键是知道它展示的是哪个区域。IDEA的Git工具窗口里有一个Commit标签页默认展示Local Changes列表其实就相当于git status点开每个文件默认显示的是工作区相对暂存区的改动。如果你想看暂存区版本需要在提交界面里换到暂存区页签。VS Code的源代码管理面板同样会显示更改列表默认对应工作区改动已经git add的文件在暂存区。搞清楚这个对应关系后IDE只是命令行的图形化不会出现IDE里看到了改动命令行diff却看不到的困惑。我经常在IDE里快速看改动但真正做提交前审查还是回命令行因为git diff --check检查空白符和--word-diff这类精细功能IDE默认界面里不一定有入口。5.5 命令速查表目标命令查看整体状态简洁git status -s看工作区未暂存改动git diff看暂存区待提交改动git diff --cached看所有未提交改动git diff HEAD只看改动文件列表git diff --name-only按文件名状态列出改动git diff --name-status看每个文件增删统计git diff --stat按词粒度查看改动git diff --word-diff检查空白符问题git diff --check临时存起未提交修改git stash -u恢复stash内容git stash pop丢弃工作区某文件改动git restore file把暂存区改动退回工作区git restore --staged file这张表我贴在工位旁边好一段时间不是背书而是在一次次真实报错里确认了边界。最后分享一个我自己的体会查看未提交的修改真正的关卡不在命令而在稳定地执行一套动作。我在Kiro项目里把这套动作固化成了status、diff、check三条命令的组合再配上那段prompt模板无论是自己提交前检查还是丢给AI做辅助审查都不会漏掉关键环节。后来我又给自己加了一条小规矩——每天早上开工先git status -s看一眼昨天留下的烂摊子再决定今天从哪开始。这个习惯坚持了几个月几乎没有再出现过改到哪里了、我忘了的尴尬。你也可以从今晚的commit前第一次全套流程开始把这套方法变成自己的肌肉记忆。