Are you an LLM? You can read better optimized documentation at /fe/git/reset-commit.md for this page in Markdown format
Git 重置提交记录 恢复历史 清理提交记录
处理密码泄漏与整理提交历史是两件不同的事。删除当前文件或重写分支,既不会让已经泄漏的凭据失效,也不能保证其他副本中的内容消失。
密码或令牌泄漏:先让凭据失效
- 立即撤销或轮换泄漏的密码、API Key、访问令牌等凭据,更新使用它们的应用与部署配置,并检查异常访问记录。不要等清理完 Git 历史才处理凭据。
- 删除代码中的秘密,改用环境变量或秘密管理工具;检查提交内容,避免把新凭据再次提交。
- 按数据敏感程度判断是否还需要清理历史。需要时,先协调协作者暂停相关分支更新,再按 GitHub 敏感数据清理指南 使用
git-filter-repo处理受影响的文件、历史路径和引用。 - 清理后复核所有受影响的分支与标签,协调协作者处理旧克隆,避免旧历史被再次推回。涉及 GitHub 的 PR 引用或缓存页面时,按官方指南联系 GitHub Support;是否能协助移除取决于具体风险。
强推不是彻底删除
旧提交仍可能存在于 fork、他人的克隆、PR 引用及缓存中。你无法通过一次推送删除所有人的副本,也不能因此认定秘密从未泄漏。不要为“方便回滚”再创建或上传含秘密的备份分支、标签或压缩包。
普通历史重置:只保留当前文件快照
如果只是希望从一个新的初始提交开始,可以创建孤儿分支。它与普通新分支不同:首次提交没有父提交,但这并不会清除其他分支、标签或远端缓存中的旧历史。
下面的示例仅适用于没有敏感数据清理需求、确定要完整保留当前已跟踪文件的普通重置。执行前须获得仓库维护者同意,与协作者约定暂停更新;确认没有进行中的合并或变基,并将需要保留的旧历史备份到受控位置、验证可恢复。若分支保护不允许强推,停止并走仓库审批流程,不要绕过保护。
1. 核对工作区与远端
先确认当前分支是 main,git status --short 没有输出,再获取远端状态:
sh
git branch --show-current
git status --short
git fetch origin
git rev-parse HEAD
git rev-parse refs/remotes/origin/main核对 origin 指向的仓库正确,且最后两个 SHA 完全一致;如果有未提交改动、未跟踪文件或本地与远端不一致,先停止处理,不要直接执行后续命令。
2. 创建并检查新快照
在同一个终端会话中保存已与远端核对一致的本地 main SHA,并从 main 创建尚不存在的孤儿分支:
sh
history_expected_main="$(git rev-parse refs/heads/main)"
git checkout --orphan clean-history main
git diff --cached --stat
git diff --cachedcheckout --orphan 会按起点准备工作区和暂存区,当前已跟踪文件已经在暂存区中,因此这里不需要 git add -A。逐项检查文件,确认没有秘密、临时文件或不应公开的内容;如果需要增删文件,按明确路径单独暂存并重新检查,不要盲目收录整个目录。
确认后提交,再检查只有一个提交、文件快照没有意外变化:
sh
git commit -m "chore: start a new history"
git rev-list --count HEAD
git diff --exit-code "$history_expected_main" HEAD --此示例完整保留原快照,因此提交数量应为 1,最后一条命令应无差异且退出码为 0。任一检查不符合预期,都不要推送。
3. 只更新指定的远端分支
再次确认获准覆盖远端 main 后,使用带明确预期 SHA 的保护推送:
sh
git push --force-with-lease="refs/heads/main:$history_expected_main" origin HEAD:refs/heads/main只有远端 main 仍指向此前核对的提交,这次更新才会成功。如果被拒绝,先查明远端是否新增了提交或存在分支保护;不要改成 --force,也不要刷新预期 SHA 后直接重试。
完成后核对远端提交与新快照,并通知协作者按约定重新克隆或迁移未合并的工作。旧的本地 main 与备份仍保留原历史,不能再把它们直接合并或推回新的 main。确认新历史可用之前,不要删除这些普通重置场景下的恢复点。
具体语义见 Git checkout 孤儿分支文档 和 Git push 的 force-with-lease 文档。
Git 学习路径
重写提交前,先了解 Git 版本回退 中 reset 与 revert 的区别;如果目标是移除大文件并缩小仓库,继续阅读 Git 缩减仓库。