假设我在本地分支上有以下提交历史:
A -- B -- C
如何在a和B之间插入新的提交?
假设我在本地分支上有以下提交历史:
A -- B -- C
如何在a和B之间插入新的提交?
其实很简单,答案就在这里。假设你在一个分支上。执行以下步骤:
在你想要插入新的提交(在本例中是commit a)之后,从commit创建一个临时分支: A .使用实例 执行更改并提交它们,创建一个commit,我们称它为N: git commit -a -m "Message" (或者git add后跟git commit) 在新的commit(在本例中是提交B和C)之后,将你想要的提交重新基于新的commit: Git重新建立临时分支
(可能你需要使用-p来保存合并,如果有的话-感谢ciekawy不再存在的注释)
删除临时分支: Git分支-d temp
在此之后,历史记录如下:
A -- N -- B -- C
当然,在改基过程中可能会出现一些冲突。
如果您的分支不是本地分支,这将引入重写历史,因此可能导致严重的问题。
这比OP的回答还要简单。
git rebase -i <any earlier commit>. This displays a list of commits in your configured text editor. Find the commit you want to insert after (let's assume it's a1b2c3d). In your editor, for that line, change pick to edit. Begin the rebase by closing your text editor (save your changes). This leaves you at a command prompt with the commit you chose earlier (a1b2c3d) as if it has just been committed. Make your changes and git commit (NOT amending, unlike most edits). This creates new a commit after the one you chose. git rebase --continue. This replays the successive commits, leaving your new commit inserted in the correct place.
当心,这将改写历史,并破坏任何试图拉扯的人。
假设提交历史是preA——A——B——C,如果你想在A和B之间插入一个提交,步骤如下:
git rebase -i hash- prea Git会打开你的编辑器。内容可能是这样的: 选A 选B 选C 更改第一个选择编辑: 编辑8668d21 选B 选C 保存并退出。 修改你的代码,然后git添加。&& git commit -m "I" Git rebase—继续
现在你的Git提交历史是preA—A—I—B—C
如果遇到冲突,Git将在此提交时停止。您可以使用git diff来定位冲突标记并解决它们。在解决所有冲突后,您需要使用git add <filename>来告诉git冲突已经解决,然后重新运行git rebase——continue。
如果你想撤销rebase,使用git rebase——abort。
更简单的解决方案:
在最后创建你的新commit, d。现在你有: A——b——c——d 然后运行: $ git rebase -i hash- a Git会打开你的编辑器,它看起来是这样的: 选B 选C 选D 只需要像这样将D移到顶部,然后保存并退出 选D 选B 选C 现在你将拥有: A d b c
这里有一个策略,可以避免在我读过的其他答案中看到的重基过程中进行“编辑黑客”。
通过使用git rebase -i,您可以获得自该提交以来的提交列表。 只需在文件顶部添加一个“break”,这将导致rebase在这一点上中断。
break
pick <B's hash> <B's commit message>
pick <C's hash> <C's commit message>
一旦启动,git rebase现在将在“中断”点停止。 现在可以正常编辑文件并创建提交了。 然后,你可以使用git rebase——continue继续进行重基。这可能会导致你必须解决的冲突。如果你迷路了,不要忘记你可以使用git rebase中止。
这个策略可以推广到任何地方插入一个提交,只要把“break”放在你想要插入一个提交的地方。
重写历史之后,别忘了git push -f。关于其他人获取你的分支的通常警告适用。
这里已经有很多好答案了。我只是想在4个简单的步骤中添加一个“无rebase”解决方案。
总结
git checkout A
# <<< modify your files at this point
git commit -am "Message for commit D"
git cherry-pick A..C
git branch -f master HEAD
解释
(注意:这种解决方案的一个优点是,直到最后一步,当你100%确定你对最终结果满意时,你才会接触你的分支,所以你有一个非常方便的“预确认”步骤,允许AB测试。)
初始状态(我假设分支名为master)
A -- B -- C <<< master <<< HEAD
1)首先将HEAD指向正确的位置
git checkout A
B -- C <<< master
/
A <<< detached HEAD
(在这里,我们可以选择使用git checkout -b temp a创建一个临时分支,而不是分离HEAD,我们需要在进程结束时删除它。这两种变体都可以工作,做你喜欢的,因为其他一切都保持不变)
2)创建要插入的新提交D
# at this point, make the changes you wanted to insert between A and B, then
git commit -am "Message for commit D"
B -- C <<< master
/
A -- D <<< detached HEAD (or <<< temp <<< HEAD)
3)然后带来最后一个丢失的提交B和C的副本(即使中间有更多的提交,命令也会是相同的,因为这是在选择一个提交范围)
git cherry-pick A..C
# (if any, resolve potential conflicts between D and these last commits)
B -- C <<< master
/
A -- D -- B' -- C' <<< detached HEAD (or <<< temp <<< HEAD)
(如果需要,可以在这里进行AB测试)
现在是检查代码的时候了,测试任何需要测试的东西,你还可以通过检查C或C'来区分/比较/检查你所拥有的和你在操作后将得到的。
4)根据你在C和C'之间的测试,它是OK还是KO。
(EITHER) 4-OK)最后,移动master的ref
git branch -f master HEAD
B -- C <<< (B and C are candidates for garbage collection)
/
A -- D -- B' -- C' <<< master
(OR) 4-KO)保持master不变
如果你创建了一个临时分支,只需使用git branch -d <name>删除它,但如果你选择分离HEAD路由,此时根本不需要任何操作,新的提交将在你用git checkout master重新连接HEAD后符合垃圾收集的条件
在这两种情况下(OK或KO),此时只需再次签出master以重新连接HEAD。
假设你想要插入的提交是由D标识的:
# Temporarily append the commit you want to insert to the end
git cherry-pick D
# Results in D -- A -- B -- C
# Start interactive rebase
git rebase -i B^
# Let's imagine that this is what the rebase prompt looks like:
# pick B Third commit
# pick A Second commit
# pick D First commit
# Then reorder the commits:
# pick B Third commit
# pick D First commit
# pick A Second commit
# Save and exit
# After completing the rebase you will find
# A -- D -- B -- C