进行交互式变基一直回到分支“开始”之前的提交(即,到最近可到达的提交,其中该文件仍然是您想要的方式)。我们称之为提交abcde
:
git rebase -i abcde
将出现待办事项列表,列出“好”提交之后的所有提交。
pick 11111
pick 22222
pick 33333
...
在待办事项列表中,标记每个提交edit
.
edit 11111
edit 22222
edit 33333
...
保存并关闭编辑器。变基将开始。当变基中的每个阶段停止并等待您的指令时,从分支之前恢复相关文件的状态:
git restore --source abcde --worktree --staged -- <pathToFile>
git rebase --continue
您的编辑会询问您是否要更改提交消息;你不需要,所以只需关闭编辑器,然后我们就可以进行下一次提交。
当您到达该过程的最后时,您将一路携带未更改的文件通过分支。
It is possible to automate everything I just said by using git filter-repo
, but you asked for a trick with interactive rebase, so that's what I described.
Also, note that if you happen know that the file in question was not altered in a particular commit, you can leave that commit set to pick
in the Todo list and thus save some steps. There are ways to find that out. But my answer is deliberately simple and ignores that issue.
我总是喜欢用一个例子来证明我的答案。开场情况如下:
* f2fa796 (HEAD -> main) three
* dc90263 two
* 4861739 one
每个提交都有一个文件a.txt,并且它从之前的提交中更改了该文件,正如我现在将展示的:
% git show HEAD:a.txt
aaa
% git show HEAD~1:a.txt
aa
% git show HEAD~2:a.txt
a
很好,让我们开始交互式变基:
% git rebase -i 4861739
在编辑器中,我将两个提交标记为edit
,然后关闭编辑器。变基开始:
Stopped at dc90263... two
You can amend the commit now, with
git commit --amend
Once you are satisfied with your changes, run
git rebase --continue
所以我说:
% git restore --source 4861739 --staged --worktree -- a.txt
% git rebase --continue
我们继续进行下一次提交。该文件中存在合并冲突,但这对我来说并不重要:
% git restore --source 4861739 --staged --worktree -- a.txt
% git rebase --continue
Git 说:
Successfully rebased and updated refs/heads/main.
现在让我们再次检查一下情况:
% git show HEAD:a.txt
a
% git show HEAD~1:a.txt
a
% git show HEAD~2:a.txt
a
这正是我们想要的结果。