我在同一个分支上有两个提交,一个接一个。我在第一次提交中添加了对文件 A 的更改,然后对其他文件进行了一些更改,然后进行了另一次提交。现在我希望对文件 A 的更改在第二次提交而不是第一次提交。最优雅的方式是什么?
5 回答
我知道这是一个老问题,但我有完全相同的要求,我只是想出了解决此问题的最佳方法:您需要使用交互式 rebase 并为要从中移动更改的两个提交选择“编辑”和到。
例如,假设您有 3 个提交:
$ git log -3 --oneline
97e9d62 Commit C, editing file2.txt
34b066b Commit B, creating file2.txt + editing file1.txt
73ff1bb Commit A, creating file1.txt
现在,如果您希望提交 B 仅包含 file2.txt 创建而不包含应该在提交 C 中的 file1.txt 版本,git rebase -i
将显示以下内容:
pick 73ff1bb Commit A, creating file1.txt
pick 34b066b Commit B, creating file2.txt + editing file1.txt
pick 97e9d62 Commit C, editing file2.txt
# ...
如果我将 Commit B 和 Commit C 的“pick”替换为“edit”或“e”并关闭我的编辑器,git 将在第二次提交时停止并让我修改我的更改:
pick 73ff1bb Commit A, creating file1.txt
edit 34b066b Commit B, creating file2.txt + editing file1.txt
edit 97e9d62 Commit C, editing file2.txt
Stopped at 34b066b... Commit B, creating file2.txt + editing file1.txt
You can amend the commit now, with
git commit --amend
Once you are satisfied with your changes, run
git rebase --continue
$ vi file1.txt # edit of file1.txt to remove the updated line
$ git commit --amend file1.txt
$ git rebase --continue
# -- git continues rebasing and stops on the Commit C to edit it
$ vi file1.txt # edit of file1.txt to put the removed line
$ git commit --amend file1.txt
$ git rebase --continue
就是这样。
注意将您从第一次提交中删除的行保存在第二个提交中。它可以在剪贴板、文本文件等中。我想它也应该可以依赖,git stash
但如果它是一个简单的更改,那么将它保存在剪贴板中会更容易。
如果它们是小提交,并且提交在 git 中应该总是很小,那么最简单的方法是 git reset HEAD^^
然后再做一次。请注意,对此的任何解决方案都涉及重写历史记录,如果您已经将这些提交推送到某个地方,除非您知道自己在做什么,否则您不应该这样做。
这个问题的另一种解决方案
- 在两次提交之前找到提交(可能这是主分支)
- 运行
git rebase -i <commit before commits to be reordered>
(git rebase -i master
大多数情况下) - 在文本编辑器中,交换提交的顺序(对于 vim,
ddp
在应该向下移动的行上使用顺序) - 保存,退出,然后让 git rebase 完成剩下的工作
在您刚刚创建了这些提交的可能不太可能发生的事件中,使用 撤消第二次提交,git reset HEAD^
然后使用 将更改添加到第一次提交git commit --amend
。
如果您已经继续前进并且提交是在过去的某个时间点,那么变基是您最好的选择。在不知道您的确切情况的情况下,引用可以很好地解释它的参考资料可能是最好的。
在第一个和第二个事件中,Pro Git 书籍关于重写历史的部分很好地解释了这些选项 - 何时应该使用它们以及何时应该谨慎使用。