最近复习了 git,发现之前写的 git如何删除某一历史纪录 - 掘金 (juejin.cn) 中对 git 的理解不到位,所以打算重新解决一下当初遇到的问题。
场景:作为新手时,我们发现仓库中存在一些私密数据,于是进行删除。但之后才发现别人依旧可以从历史记录中获取这些私密数据,那我们应该怎么从历史记录中删除私密数据呢?(该问题有更好、更方便的解决方案,但本文还是聚焦于使用 edit 命令来解决)
我们以 test 文件为例,来讲解以下内容。目前私密数据已被删除(在第三行)
先看看原始的提交记录,为了方便讲解,我为一些提交设置了标签:
可以看到,在 a 提交时,引入了一些私密数据,虽然在 d 提交中已经将其删除,但从历史记录中依然可以访问到私密数据。故我们的目的就是将 a,b,c 中的私密数据删除(d 提交中我们已经删除了,所以不需要再次处理)。
首先,我们进入交互式 rebase:
$ git rebase -i a^
# 这里借助了相对引用符号(^)来表示 a 提交的前一个提交
然后,在需要处理的提交前设置命令 edit
现在,我们就会进入 a 提交了,我们先将私密数据删除
然后保存该变更:
git add -A
然后继续进入下一个提交(b):
git rebase --continue
此时我们可以修改一些注释信息,来方便讲解。
进入 b 提交后,步骤是一样的,修改文件内容,然后继续 rebase。
此时你可能和我一样,遇到冲突:
但没关系,这并不影响我们的操作,因为不管有没有冲突我们都会修改该文件。继续删除我们的私密数据:
然后继续执行下面命令:
git add -A
git rebase --continue
神奇的事情发生了,进入 c 提交后我们会发现私密数据消失了!
这是怎么回事呢?这是因为 c 提交所作出的变更仅仅只是添加了新的一行,并没有对“私密数据”进行处理。(了解到这里已经足够了,再继续下去就得解释 git 是如何存储变更的了,这是另外一个话题。)所以此时我们只需要执行命令 git rebase --continue。(但这里,我为了在 c 提交的注释信息中添加说明,所以我先执行 git commit --amend 来修改注释信息。你并不需要像我一样操作。)
到这里我们的最重要的工作已经完成了,还剩下一些收尾工作:
由于我们没有对 c 提交上做任何变更(注释信息不算),而 d 提交上所做出的变更也早已消失(此前的 d 提交上做的变更是删除私密数据)。所以当你在 c 提交中执行 git rebase --continue 命令后,控制台输出了以下内容:
$ git rebase --continue
interactive rebase in progress; onto c096d34
Last commands done (4 commands done):
edit 26de6ef regular work2
pick d25876c delete secret data
(see more in file .git/rebase-merge/done)
Next command to do (1 remaining command):
pick 3a0523c foo
(use "git rebase --edit-todo" to view and edit)
You are currently rebasing branch 'main' on 'c096d34'.
(all conflicts fixed: run "git rebase --continue")
nothing to commit, working tree clean
The previous cherry-pick is now empty, possibly due to conflict resolution.
If you wish to commit it anyway, use:
git commit --allow-empty
Otherwise, please use 'git rebase --skip'
Could not apply d25876c... delete secret data
它的意思就是说现在的 d 提交没有进行任何更改,我们可以选择创建一个空提交或者直接忽略 d 提交。在这里我们选择创建一个空提交,因为这样可以添加注释信息。
(不管你是否创建一个空提交,你都需要)继续运行 git rebase --continue,然后我们就完成了整个 rebase 过程了。完成后如图所示:
如果你没有选择添加注释信息,也没有创建空提交,那么你的结果可能是这样的:
现在,我们已经在本地完成所有工作了,最后再将本地变更强制推送到云端就可以了:git push --force