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

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

当你想开源某个内部开发很久的项目或者有一些脚本想要上传到 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

IMG

分支状态

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

IMG

IMG

分支状态

a - b - c - d master
a - e temp
  1. 第三步,使用 git rebase 合并两个提交,git rebase 合并两个分支的操作请参考这篇文章,使用git rebase合并多次commit - zuopf769 - 掘金
# 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 交互操作界面,windows/mac 通用,无需下载

IMG

也就是 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 操作部分,保留你需要提交信息

IMG

合并后

IMG

分支状态

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

IMG

IMG

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

IMG

实际应用

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

基于 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 怎么办?

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

IMG

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

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

IMG

IMG

  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 会丢失,如下图

IMG

总结

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

参考资料

  1. git cherry-pick 教程 - 阮一峰的网络日志
  2. 不小心把密码上传到 GitHub 了,怎么办 - Benny 小土豆
  3. How to cherry-pick multiple commits - stackoverflow
相关文章
|
16天前
|
SQL 存储 监控
|
1月前
|
JavaScript Java 关系型数据库
农业信息|基于SSM+vue的农业信息管理系统的设计与实现(源码+数据库+文档)
农业信息|基于SSM+vue的农业信息管理系统的设计与实现(源码+数据库+文档)
41 0
|
14天前
|
监控 关系型数据库 Java
|
28天前
|
关系型数据库 MySQL 应用服务中间件
tomcat 搭建博客 及破解数据库密码
tomcat 搭建博客 及破解数据库密码
|
1月前
|
小程序 JavaScript Java
高校宿舍信息|基于Spring Boot的高校宿舍信息管理系统的设计与实现(源码+数据库+文档)
高校宿舍信息|基于Spring Boot的高校宿舍信息管理系统的设计与实现(源码+数据库+文档)
33 0
|
1月前
|
SQL Oracle 关系型数据库
实时计算 Flink版产品使用合集之从Oracle数据库同步数据时,checkpoint恢复后无法捕获到任务暂停期间的变更日志,如何处理
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStreamAPI、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
14天前
|
SQL 运维 关系型数据库
|
14天前
|
存储 开发工具 git
蓝易云 - git中,add到暂存区,commit且push之后,暂存区域里还有内容吗
所以,当你执行 `git add`,然后是 `git commit`,最后是 `git push`之后,暂存区是空的,除非你又执行了新的 `git add`命令来添加更多的更改。
17 1
|
19天前
|
Oracle 关系型数据库 MySQL
深入了解 Linux 命令 `db_stat`:数据库统计信息的获取
本文模拟了 Linux 环境下使用 `db_stat` 命令获取数据库统计信息的场景,实际上`db_stat`是特定数据库系统的自定义工具。文章通过示例展示了如何针对Oracle、PostgreSQL和MySQL使用各自内置命令收集统计信息,强调了权限、性能影响和数据实时性等因素,并指出这些信息对优化数据库管理至关重要。
|
16天前
|
JavaScript 关系型数据库 MySQL
Python实战:从猎聘网获取职位信息并存入数据库
Python实战:从猎聘网获取职位信息并存入数据库

热门文章

最新文章