git彻底移除敏感文件

前言

在日常开发项目中,可能会出现将包含数据库连接字符、中间件密钥等敏感信息提交并推送到远程仓库的情况,这时需要将文件删除。执行git rm config.json命令虽然删除了文件,但是在历史提交记录中仍然可以查看到数据内容。这时可以使用 核武器级选项:filter-branch

移除数据

filter-branch

描述

允许您通过重写 <rev-list options> 中提到的分支来重写 Git 修订历史,在每个修订上应用自定义过滤器。这些过滤器可以修改每棵树(例如删除文件或对所有文件运行 perl 重写)或有关每次提交的信息。否则,将保留所有信息(包括原始提交时间或合并信息)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 移除test文件夹下config.json 文件,并擦洗所有涉及此文件的提交历史。
git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch test/config.json' --prune-empty --tag-name-filter cat -- --all

# 移除test文件夹下所有文件,并擦洗所有涉及此文件的提交历史。
git filter-branch --force --index-filter 'git rm -r --cached --ignore-unmatch test' --prune-empty --tag-name-filter cat -- --all

# 当你检查项目后,发现没有任何问题,则将命令提交到版本库中。
git push origin --force --all

# 你还需要提交你的git tags,用以更新服务器的git tags。
git push origin --force --tags

# 删除本地缓存
git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
git reflog expire --expire=now --all
git gc --prune=now

命令说明:git filter-branch

option

1
2
--f 
--forece

git filter-branch 拒绝以现有的临时目录开始,或者当已经使用 refs / original / 开始refs时,除非被强制。

1
--index-filter <command>

这是重写索引的过滤器。它类似于树过滤器,但不检查树,这使得它更快。经常与git rm –cached –ignore-unmatch …一起使用

1
--prune-empty

某些过滤器将生成空提交,使树保持不变。如果git-filter-branch只有一个或零个非修剪父项,则该选项指示git-filter-branch删除这些提交;因此,合并提交将保持不变。此选项不能与--commit-filter一起使用,但通过在提交过滤器中使用提供的git_commit_non_empty_tree功能可以实现相同的效果。

1
--tag-name-filter <command>

这是用于重写标记名称的过滤器。传递时,将为每个指向重写对象(或指向重写对象的标记对象)的标记ref调用它。原始标记名称通过标准输入传递,新标记名称在标准输出上是预期的。
原始标签不会被删除,但可以被覆盖;使用“—tag-name-filter cat”来简单地更新标签。在这种情况下,请务必小心并确保备份旧标签,以防转换发生冲突。
支持几乎正确的标记对象重写。如果标记附加了消息,则将使用相同的消息,作者和时间戳创建新的标记对象。如果标签附有签名,则签名将被删除。根据定义,不可能保留签名。这是“几乎”正确的原因,因为理想情况下,如果标签没有改变(指向同一个对象,具有相同的名称等),它应该保留任何签名。情况并非如此,签名将永远删除,买家要小心。也不支持更改作者或时间戳(或标记消息)。指向其他标记的标记将被重写以指向底层提交。

缩小存储库的清单

git-filter-branch可用于删除文件的子集,通常使用–index-filter和–subdirectory-filter的某种组合。人们期望生成的存储库小于原始存储库,但是你需要更多的步骤来实际使它变小,因为Git努力不会丢失你的对象,直到你告诉它。首先要确保:

  • 如果blob在其生命周期内被移动,那么您确实删除了文件名的所有变体。 git log –name-only –follow –all – filename可以帮助您找到重命名。
  • 你真的过滤了所有的refs:在调用git-filter-branch时使用–tag-name-filter cat – –all。
    然后有两种方法可以获得更小的存储库。更安全的方法是克隆,保持原始原封不动。

用git clone file:///path/to/repo克隆它。克隆将没有删除的对象。参见 git-clone [1] 。 (请注意,使用普通路径进行克隆只会将所有内容硬链接!)

忽略文件更新

  1. 情况:始终不需要git跟踪本地的一些文件
    • 方法:使用.gitignore文件忽略
    • 使用git init操作创建git控制管理之后,默认不会生成.gitignore文件。我们可以创建该文件,将对应的不需要的文件名或文件夹名添加进去。后面再使用git add .对所有新增文件更新到 git管理系统时不会追踪.gitignore中的文件,也不会在使用git status操作时有提示。
    • .gitignore适合添加一些IDE的配置文件,避免自己的配置文件在于他人协作或者项目迁移时产生影响。也适合添加编译生成的一些中间文件,以便保证git中添加的均为源代码。
    • 需要注意的是.gitignore是用于管理不在index tree的文件,如果不小心将文件添加了进去,可以先使用git rm --cached filename命令将文件从托管中移除(不会删除文件本身),.gitignore就会生效。
  2. 情况:不需要将文件以后的更改更新到git,但是需要保留目前git中文件的状态
    • 方法:git update-index --assume-unchanged filename
    • 该操作标记文件,该文件后续的变化都不会更新到index tree。
    • 如果需要恢复对文件的版本控制,执行以下操作: git update-index --no-assume-unchanged filename

Note

du -hs <flie/folder>:查询文件/文件夹占用大小

参考:

Git 工具 - 重写历史
Git移除敏感数据
Linux du 命令
git使用-忽略文件更新的几种方法

作者

zhang

发布于

2022-07-29

更新于

2023-09-19

许可协议

CC BY-NC-SA 4.0

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×