最近在写 android app 大作业的时候用到了 git 管理项目,今天给它加上了 release 的 signingConfigs ,方便在 gradle task 中自动签名。
我的 app 签名基本用的都是同一个 keystore 文件,里面有密码。写的时候直接从老项目复制了一个 keystore 过来。
然而我没注意创建文件的时候 keystore.properties 已经被 AS 自动 add 到缓存里面了。测试完成之后,直接提交,才发现我的 keystore 文件已经出现在了 git 的历史里面。
于是我赶紧把这个提交在 AS 的 git ui 里面给 undo 了,然后在 gitignore 补上 keystore ,重新提交——这样看起来好像就完事了。
泄露密码的危机这样就解决了吗?我想起以前看 git book 的时候有这么一句话:
记住,在 Git 中任何 已提交 的东西几乎总是可以恢复的。
因此事情或许没那么简单,不能这么草率地就 push 到 github 上了。
回顾之前的操作,我们需要找到误提交那次的 hash ,由于它已经不在 master 分支上,因此找起来就麻烦了。
好在 AS 有一个 console ,里面记录了 git 命令的调用流程。
398b6bc
就是把 keystore 提交上去的那个 commit 。
使用 git reflog
查看,它果然还在:
把它 checkout 出来看看:
git branch wtf 398b6bc
在这个分支可以看到被提交上去的 keystore 和其中的密码。
观察到 reflogs 不仅包含了我们 undo 的那次提交,甚至还有以前 amend 的提交。那么这些 ref 到底会不会被推送到 remote 呢?
于是我从 github 上又 clone 了一份仓库下来,观察它的 reflog ,发现只有一条:
尝试 checkout 一个 amend 的提交,发现是不能的:
# 在原来工作的本地仓库 git reflog
073aec9 HEAD@{14}: commit (amend): generator: support share qrcode
8fe6c00 HEAD@{15}: commit: generator: support share qrcode
# 在新 clone 的本地仓库
D:\Documents\tmp\Scanner>git branch aa 8fe6c00
fatal: Not a valid object name: '8fe6c00'.
D:\Documents\tmp\Scanner>git branch aa 073aec9
看起来本地的 ref 并没有都推送到 remote 。
实际上,reflog 看到的是 local 仓库的 ref 记录。
Git - git-reflog Documentation
AS 中 undo commit 用的是 reset --soft
,那么这样推送到远程是否安全呢?查了几个回答,得到的答案都是肯定的:
从上面的实验来看,那些 amend 的提交仅存在于本地,从远程再拉回来是不存在的。这样总算可以大胆地 push 了。
在仓库目录里面放 keystore 还是有些危险,一不小心就会出现这样的差错,好在 undo 还是有效的。
仔细想想,如果在 gradle 里面从 home 目录读取 keystore 也许会更好。