大家好呀,我是yangyang.今天看到一个实用的git操作工具,分享给大家
概述
在软件开发中很有可能出现一些严重错误。 比如不小心将 API 密钥直接提交到配置文件中,而不是使用属于 .gitignore 一部分的 .env 文件。 我的存储库仍然是私有的,但由于计划公开,我需要从 git 历史记录中删除此信息。
如何从我的历史记录中删除包含敏感信息的提交? 经过一番研究,我决定使用 git filter-branch 命令。 最终,它按照预期发挥了作用。 我没有从 git 历史记录中丢失任何其他内容,只有与某些配置文件相关的提交以及我必须在备份分支的帮助下重新创建的配置文件本身。
无论您是经验丰富的开发人员还是版本控制领域的新手,本指南都将提供清晰的分步方法,以确保从与特定文件相关的分支中安全地删除提交。
git filter-branch
关于git filter-branch,它是一个强大但危险的git工具。 它允许您以各种方式修改提交历史记录,例如更改提交消息、作者详细信息,或者像我一样,删除包含 API 密钥等敏感信息的提交。 它的工作原理是过滤整个分支历史记录,根据您指定的更改重新提交。
请谨慎使用。 它可能会导致数据丢失或项目历史记录出现差异。 建议在受控环境(如私有存储库)中使用此工具,并确保在继续操作之前拥有完整的数据备份。 此外,如果您在团队中工作,与同事协调对于避免历史记录更改后发生冲突或数据不一致至关重要。 使用前请检查文档,尤其是安全信息。 Git 过滤器-分支文档:https://git-scm.com/docs/git-filter-branch
案例指南
假设分支名为 Secret_keys,我在其中提交了 Secret_key 并将其推送到 config.js 文件中。
首先,我将 .env 添加到我的 .gitignore 并将其推送到存储库。 之后,我创建了不属于版本历史记录的 .env 文件,并将密钥从我的 config.js 添加到该文件,我引用了 .env 文件,而不是在 config.js 文件中硬编码密钥 本身。
在这种情况下,密钥在版本控制中可用。 我必须摆脱这个。 这里是 git filter-branch 命令。 但首先,为了安全起见,让我创建一个备份分支:secret_key_backup。
然后我在项目中打开一个终端,并确保我位于所需的分支上:
git checkout secret_keys
为了安全起见必须删除的主要提交
接下来,运行 git filter-branch 命令:
git filter-branch --force --index-filter "git rm --cached --ignore-unmatch file_containing_secret_keys.js" --prune-empty --tag-name-filter cat -- branch_name_containing_commits_to_remove
- git filter-branch:启动重写 git 历史记录的过程。
- --force:强制重写历史记录,如果您之前已经运行过filter-branch,则这是必要的。 覆盖安全检查以防止覆盖现有备份。
- --index-filter:指定一个过滤器以在每次修订时重写索引。
- “git rm --cached --ignore-unmatch file_having_secret_keys.js”: --index-filter 为每次提交运行的命令。
- git rm --cached:从索引(暂存区域)中删除指定文件,但不从工作目录中删除。
- --ignore-unmatch:如果在特定提交中找不到文件,则防止出现错误。
- file_containing_secret_keys.js:您要从历史记录中删除的特定文件。
- --prune-empty:告诉 git filter-branch 删除应用过滤器后变空的提交。
- --tag-name-filter cat:此过滤器应用于指向重写提交的标签名称。 cat 仅保留原始标签名称。
- --:分隔符,阐明选项的结尾和分支规范的开头。
- branch_name_containing_commits_to_remove:指定要重写其历史记录的分支。
此命令专门用于从给定分支的历史记录中删除特定文件,从而消除提交中对该文件的所有引用。
案例中:
git filter-branch --force --index-filter "git rm --cached --ignore-unmatch config.js" --prune-empty --tag-name-filter cat -- secret_keys
**WARNING**: git-filter-branch has a glut of gotchas generating mangled history rewrites. Hit Ctrl-C before proceeding to abort, then use an alternative filtering tool such as 'git filter-repo' (https://github.com/newren/git-filter-repo/) instead. See the filter-branch manual page for more details; to squelch this warning, set FILTER_BRANCH_SQUELCH_WARNING=1.
Proceeding with filter-branch...
Rewrite a3a48b09e282854c80bf4ad02a017e249e161fd8 (2/8) (0 seconds passed, remaining 0 predicted) rm 'config.js'
Rewrite 6e788e83a338e45b348d93d682b32c816ee2fbff (3/8) (0 seconds passed, remaining 0 predicted) rm 'config.js'
Rewrite 7a378a0145bce70bea213ca5f9062138544db5f2 (4/8) (0 seconds passed, remaining 0 predicted) rm 'config.js'
Rewrite 0637c9659623644cfceb35be10f2a1fe5c468e04 (5/8) (0 seconds passed, remaining 0 predicted) rm 'config.js'
Rewrite 6c421eb99adc6b987cff7f3cada31e9313638072 (6/8) (0 seconds passed, remaining 0 predicted) rm 'config.js'
Rewrite 98001e5b97270efa4a8ab5bd0452be56dd76883d (7/8) (0 seconds passed, remaining 0 predicted) rm 'config.js'
Rewrite 2ca4e161a4af2b8f38c46faf848fdbb3e550f23c (8/8) (0 seconds passed, remaining 0 predicted) rm 'config.js'
Ref 'refs/heads/secret_keys' was rewritten.
在图像中,可以看到剩下 2 个提交,因为我所做的占位符提交与 config.js 相关,因此它们也被删除了。 如果我提取存储库,那么我将返回到之前的状态,以便此时可以从存储库检索已删除的提交。 它将创建一个合并提交,可以将其推回,然后所有提交都将被恢复,但我们希望它们被删除。
要应用修改,您需要强制推送:
git push origin branch_name_containing_commits_to_remove --force
# 当前案例
git push origin secret_keys --force
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 8 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 293 bytes | 293.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To https://github.com/Balogh08/GitFilterBranch.git
+ 2ca4e16...e61bbd2 secret_keys -> secret_keys (forced update)
现在 提交和曾经包含敏感信息的文件现在已被删除
接下来,我们需要替换没有敏感信息的文件。 为此,我们可以使用备份分支复制 config.js 的内容,并在分支中创建一个新的 config.js,而无需敏感提交。 然后,粘贴备份分支中的内容。 如果您没有发布备份分支,那么您可以轻松删除它。 但是,如果您发布了它,则必须在备份分支上使用 git filter-branch 执行相同的过程,但无需为备份创建第二个备份。 简单地从远程存储库中删除分支是不够安全的,因为包含敏感信息的提交的密钥将保留在源代码控制系统中的某个位置。
大家更喜欢什么替代方案,例如 git filter-repo? 请在评论中告诉我。