Git删除敏感密钥

目录

删除git敏感密钥

如果你现在遇到了这个场景,在github 上不小心 上传了私钥操作

同时新版本 已经领先于之前的版本了

输入git log 如下:

这是我的模拟场景

commit 0ed3d55db179964998d83076dd3f6f87849de84a (HEAD -> main, origin/main, origin/HEAD)
Author: jacinli <poplar_ripest80@icloud.com>
Date:   Tue Mar 25 23:29:02 2025 +0800

    test

commit ec8ce5a6647f1c9ee17cfa6652d70b19edc43c92
Author: jacinli <poplar_ripest80@icloud.com>
Date:   Tue Mar 25 23:28:40 2025 +0800

    Add .env.dev file for development environment configuration with test secret.

✅ 你的目标是:

彻底从 Git 历史中清除敏感内容(如私钥)

保留当前的提交记录(不丢 0ed3d55)

推送到 GitHub 覆盖远程历史

✅ 1. 安装 Git Filter Repo(推荐)

brew install git-filter-repo  # macOS
# or
pip install git-filter-repo  # 跨平台

✅ 2. 备份当前分支,防止误操作!

git branch backup-main

✅ 3. 使用 git-filter-repo 清除敏感文件 [注意备份】

git filter-repo --force --path .env.dev --invert-paths

⚠️ 注意:该命令会修改你的整个 Git 历史!如果你误操作,当前目录无法恢复!请先备份!

确实会导致 本地仓库和远程仓库之间的关联信息被清除掉,原因如下:

🧠 为什么远程信息会丢失?

git filter-repo 本质上是重写历史,它会:

移除 Git 的 .git/config 中的 remote 配置

抹除 reflog 和旧 commit

相当于初始化了一个新的 repo 结构(尽管你还在旧目录里)

1. 重新添加远程仓库

git remote add origin git@github.com:your-username/your-repo.git
# 或者如果你用 https
# git remote add origin https://github.com/your-username/your-repo.git

让本地追踪远程main:

git branch --set-upstream-to=origin/main main

永久性地从历史中

删除这个文件

先看一下当前的远程地址:

git remote -v

如果输出为空,说明确实没有 remote。

✅ 解决办法:重新绑定远程仓库并设置追踪分支 [见上面的处理】

# 1. 添加远程仓库(如果还没添加)
git remote add origin git@github.com:your-name/your-repo.git  # 替换成你自己的仓库地址

# 2. 设置 main 分支追踪远程 origin/main 分支
git branch --set-upstream-to=origin/main main

# 3. 推送并强制覆盖远程历史(⚠️慎用)
git push origin main --force

✅ 4. 强制推送(会覆盖远程历史)

git push origin main --force

恢复操作

在上面结束后,不可以直接merge了,因为commit历史不一样了

解决办法如下: 更改名称+更换远程分支为None,然后checkout对应的分支,接着对着之前的文件合并自己的stash信息操作,如果不小心删除了自己的一个分支,恢复如下:

✅ 步骤一:查看 Git 的操作日志(reflog)

git reflog

日志:

9b447a7 HEAD@{1}: Branch: renamed refs/heads/dev to refs/heads/dev1
9f58874 (HEAD -> dev) HEAD@{0}: checkout: moving from dev1 to dev

恢复分支:

git checkout -b dev1 9b447a7

为什么不删除hash值?

Git 是一个基于有向无环图(DAG)的内容寻址版本控制系统,不能直接“删掉某个 hash 对应的 commit”,因为那会破坏整个历史链条。

🧠 更详细解释:

1. Git 的核心是不可变的对象(内容寻址)

• Git 的每个提交(commit)都是一个对象。

• 它包含:

• 当前代码快照的指针(tree)

• 父提交(parent hash)

• 提交信息

• 作者信息

• hash 是根据内容生成的,一旦生成,就不可更改,也不可直接“删除”一个中间 commit,否则后面所有 commit 都会“失联”。

2. 中间提交不能随便删:因它被后面的 commit 引用了

假如你强行删除一个 commit:

git cat-file -t <commit_hash>  # 确认类型是 commit

你无法从 Git 的内部对象数据库中直接删掉这个 commit:

因为: • 后续提交依赖它 • Git 的对象之间是通过 hash 引用的 • 删除一个 commit 之后,它的“子孙”都会失效

3. 正确方式是“重写历史”

git filter-repo --path .env.dev --invert-paths

Git 的哲学:

历史是不可变的

❌ Git 不允许你直接删除某个 hash(commit),因为它是整个历史链的节点;

✅ 正确方式是用工具“重写历史”,然后强推。

使用Revert

Git 中的 revert 命令的设计目的,是:

不破坏历史、但能“撤回”某次提交的内容。

换句话说:

• revert 不删除旧的 commit;

• 它是创建一个新的 commit,这个 commit 的内容是“反操作”;

• 你可以想象为:“加了一个反向 patch”。

A - B - C - D   现在 HEAD  D

执行:

git revert C

Git 会生成一个新的 commit(比如 E):

A - B - C - D - E

这个 E 是“把 C 做的内容撤销”的补丁,但 C 本身 仍然存在

❓那为啥不直接删除 C?

因为 删除 C 就会影响整个历史链条

• 如果你硬删了 C,那么 D 也会失效(因为它是基于 C 的快照);

• 这就破坏了历史的完整性;

• Git 的设计理念是:

不可篡改的 commit 历史,是协作安全的基础。

🔍 revert vs reset vs rebase vs filter-repo

命令 作用 是否保留历史 是否安全协作
revert 生成一个“反向补丁” ✅ 是 ✅ 是
reset 改变当前分支指向 ❌ 否 ⚠️ 会影响别人
rebase 重写提交历史 ❌ 否 ⚠️ 要小心共享分支
filter-repo 深度修改整个历史 ❌ 否 ⚠️ 仅在重写整个仓库历史时使用

git revert 的存在,是为了

“在不破坏历史的前提下撤销某次提交的内容”

点赞一下

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦