likes
comments
collection
share

如何处理 git 中包含数据库密码等隐私信息的 commit?

作者站长头像
站长
· 阅读数 52

当你想开源某个内部开发很久的项目或者有一些脚本想要上传到 github,但是这个项目的 git 版本管理中包含了你以前填入的数据库密码,而且是明文,这时候就非常麻烦,这种情况需要如何处理保证项目的 git 能够保证最小修改,尽可能的不去修改过多 commit?看如下操作

PS: 只是单纯删掉密码并新提交一个 commit 是无法修改掉 git 版本管理中的历史的

新建临时分支覆盖

这个办法的主旨思路是基于 gitcherry-pickrebase 和 命令赋能临时分支,将需要涉及泄密的 commit 重新拿出来然后再合并,操作如下

  1. 第一步,基于修改密码的 commit 创建临时分支 temp,假设下面的 a 是初次提交时携带了数据库密码的 commit

git 操作

# 查看你的 commit id(SHA)
git log
git checkout commit-id
git branch temp
git checkout temp

PS: 你可以在 VS Code 的 gitlen 插件提供的 graph 来获取 commit id 而不是查看终端或者命令行的 commit id

如何处理 git 中包含数据库密码等隐私信息的 commit?

分支状态

old
a - b - c - d master
new
a - b - c - d master
a temp
  1. 第二步,删除密码或者改为环境变量(比如 dotenv),并提交一个新的 commit

如何处理 git 中包含数据库密码等隐私信息的 commit?

如何处理 git 中包含数据库密码等隐私信息的 commit?

分支状态

a - b - c - d master
a - e temp
# commit a 是初始提交,HEAD 指针在 commit e 上
# 所以是 --root
# 一般情况是 HEAD~n, n 指需要合并的 commit 数目
# https://stackoverflow.com/questions/26174757/git-needed-a-single-revision-error
git rebase -i --root

进到 vim 交互操作界面,如果你的不是 vim,可以执行 swindows/mac 通用,无需下载

如何处理 git 中包含数据库密码等隐私信息的 commit?

也就是 s c31a5ed init,其中 s 是对需要合并的 commit 执行的命令,s 包括其它命令信息如下

# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit

pick:保留该commit(缩写:p)
reword:保留该commit,但我需要修改该commit的注释(缩写:r)
edit:保留该commit, 但我要停下来修改该提交(不仅仅修改注释)(缩写:e)
squash:将该commit和前一个commit合并(缩写:s)
fixup:将该commit和前一个commit合并,但我不要保留该提交的注释信息(缩写:f)
exec:执行shell命令(缩写:x)
drop:我要丢弃该commit(缩写:d

vim 中执行 esc -> :wq 保存退出,进入 commit message 操作部分,保留你需要提交信息

如何处理 git 中包含数据库密码等隐私信息的 commit?

合并后

如何处理 git 中包含数据库密码等隐私信息的 commit?

分支状态

a - b - c - d master
f temp
  1. 第四步,cherry-pick 原分支的剩下的 commit
# 注意 b 和 d 是 master 分支 commit 的 hash 值,也就是 commit id
# b^..d 表示迁移包含 b 在内到 d 的 commit
# 使用 windows 的 cmd 需要使用 "b^..d" 因为 ^ 需要转义
# 参考:https://stackoverflow.com/questions/1670970/how-to-cherry-pick-multiple-commits
git cherry-pick b^..d

如何处理 git 中包含数据库密码等隐私信息的 commit?

如何处理 git 中包含数据库密码等隐私信息的 commit?

  1. 第五步,将临时分支转正,替换成 master 分支,完成此步可以修改完成
git checkout temp
git branch -d master
git branch -M master
# 如果还有远程仓库并想同步,需要强制推送并覆盖
# git push -f origin

如何处理 git 中包含数据库密码等隐私信息的 commit?

实际应用

出于教学目的,上面的处理例子是根据实际情况模拟的,实际过程中会

基于 master 分支新建一个 temp1 分支,然后再基于 temp1 分支新建 temp2 分支,在 temp2 分支执行 rebase 操作,目的是为了提高容错,保证后续出错以后可以回到 master

而在实际应用时还遇到了一些问题如下

cherry-pick 多个 commit 中间遇到错误

举个例子,分支状态如下

a - b - c - d master
f temp

操作如下

# windows
git cherry-pick "b^..d"
# 如果在 cherry-pick 到 c 的过程中出错了怎么办?

上面引出了两个问题

  1. git cherry-pick c 出错了如何解决
  2. git cherry-pick c 导致后面的 commit d 要如何继续合并?d 后面有更多的 commit 怎么办?

首先解决第一个问题,出错问题可以百度或者谷歌,案例很多,举一个本文章实际例子

如何处理 git 中包含数据库密码等隐私信息的 commit?

上面这个就是合并 2adf3c9 这个 commit 过程中遇到了冲突,所以遇到这种情况即证明 cherry-pick 中途遇到了错误,没有完成全部 cherry-pick,而对于冲突的解决请查阅文档 解决完冲突之后就可以处理第二个问题,继续 cherry-pick 剩下的 commit,这个时候有两种方法

  1. 第一种方法,git cherry-pick --continue,继续剩下的合并,如果再出错,先根据提示信息处理错误,然后再次进行 git cherry-pick --continue,直到出现下图两种情况之一

如何处理 git 中包含数据库密码等隐私信息的 commit?

如何处理 git 中包含数据库密码等隐私信息的 commit?

  1. 第二种方法,根据中断的 commit 再进行一次合并,比如上面的例子,在 c 部分出错,就可以在解决错误之后执行 git cherry-pick "c..d""c..d" 指合并不包含 commit c),命令如下
# 先中止上一次的 cherry-pick
git cherry-pick --abort
git cherry-pick "c..d"

未跟踪文件导致 cherry-pick 失败

这个问题比较特殊,错误信息如下

error: The following untracked working tree files would be overwritten by merge:
        .vscode/settings.json
Please move or remove them before you merge.
Aborting
fatal: cherry-pick failed

意思就是 cherry-pick 的某次提交中存在和当前没有被提交到暂存区(即没有被跟踪)的文件的名称一致的文件,解决方法很简单,就是在 cherry-pick 之前本地这个没有被提交到暂存区(即没有被跟踪)的文件,即 .vscode/settings.json 即可

但是注意,你解决完错误以后就不能使用上面的方法 cherry-pick 多个 commit 中间遇到错误

因为这个意味着你的 git cherry-pick "b^..d" 已经失败了,没有 git cherry-pick --continue 的机会了

继续举 commit c 出错的例子,再次强行 git cherry-pick --continue 的结果就会使 c 会丢失,如下图

如何处理 git 中包含数据库密码等隐私信息的 commit?

总结

使用临时仓库覆盖是非常侵入性的操作,看完整篇文章后你可以比较前后 master 分支的 commit id 或者说 HASH 值,已经完全改变,如果这是一个多人操作的库,这样的操作是毁灭性的,必须通知其它人,否则会导致难以挽回的冲突

参考资料

  1. git cherry-pick 教程 - 阮一峰的网络日志
  2. 不小心把密码上传到 GitHub 了,怎么办 - Benny 小土豆
  3. How to cherry-pick multiple commits - stackoverflow
转载自:https://juejin.cn/post/7169953671004831774
评论
请登录