这几天开发一个功能,改动了一个不需要改动的文件,最后提交 code review 的时候显得很多余,就想把他还原回去,为了达到这个目的,一开始能想到以下几种比较容易的办法:

  • 最简单的办法是从main分支上复制该文件粘贴到我的分支,再git commit一次

  缺点:这样以后别人也能看到 git log 里有我的改动记录,可能给将来追溯提交历史带来困难

  • git reset到该文件修改之前,然后取消该文件的修改,再把其他文件重新 commit 一次

  缺点:如果那次提交之后有很多次提交,提交信息都将丢失,只保留现在的提交了

  我想要的是仓库历史提交信息不能动,主要是提交时间和提交说明必须保留原样,但是查看这个单文件的提交历史时,不能出现我的提交。

  此时需要使用 git rebase 命令。

  假设我们一开始初始化仓库,main 分支只有一个提交记录,包含a.txtb.txt两个文件。此时我们建立一个 feature 分支:

移除git仓库关联 git删除本地仓库的commit_编辑器

  然后在feature分支上进行三次提交,其中第一次和第三次提交都只改动 a.txt 这个文件,第二次提交会改动 a.txtb.txt两个文件。

  仓库的git log

移除git仓库关联 git删除本地仓库的commit_bc_02

  a.txtgit log

移除git仓库关联 git删除本地仓库的commit_vim_03

  b.txtgit log

移除git仓库关联 git删除本地仓库的commit_移除git仓库关联_04

  我们需要达到的效果是仓库的git log会出现三个提交,但是b.txt单文件历史不能出现任意一个提交。

  执行命令git rebase -i f486467f2553547eda75c90d2dcf3c791e70cfbc(最后那一长串是第一次提交的 commitid):

移除git仓库关联 git删除本地仓库的commit_移除git仓库关联_05

  根据说明,我应该把第二次提交那一行(也就是第一行)的第一个单词pick改成e,这样我就可以修改文件内容了,vim 修改完成后:

移除git仓库关联 git删除本地仓库的commit_git_06

  此时我再去把b.txt还原为main分支的内容(复制粘贴),然后执行:

git add -A
git rebase --continue
复制代码

  这时候又需要 vim 操作:

移除git仓库关联 git删除本地仓库的commit_移除git仓库关联_07

  我们把第一行的提交信息改为“第二次提交,只改动 a”,然后保存:

移除git仓库关联 git删除本地仓库的commit_bc_08

  这时候我们再看看仓库的git log

移除git仓库关联 git删除本地仓库的commit_vim_09

  a.txtgit log

移除git仓库关联 git删除本地仓库的commit_vim_10

  b.txtgit log

移除git仓库关联 git删除本地仓库的commit_移除git仓库关联_11

  feature分支与main分支的比较:

移除git仓库关联 git删除本地仓库的commit_移除git仓库关联_12

  切到main分支后,执行git merge feature

移除git仓库关联 git删除本地仓库的commit_git_13

  可以看到,b 文件没有提交记录了,但是 a 文件的三次提交都在,最棒的是第二次提交的时间还是之前的时间!