假设我在我的本地分支上有以下提交历史:
A -- B -- C
我该如何在A
和B
之间插入一个新的提交?
这比OP的回答还要简单。
git rebase -i <任意早期提交>
。这将在您配置的文本编辑器中显示提交列表。a1b2c3d
)。在您的编辑器中,对于该行,请将pick
更改为edit
。a1b2c3d
)的命令提示符下,就好像刚刚提交了该提交。git commit
(与大多数edit
不同,不修改原始提交)。这会创建一个新提交,在您选择的提交之后。git rebase --continue
。这将重新应用连续的提交,将您的新提交插入正确的位置。请注意,这将重写历史记录,并且会破坏尝试拉取提交的其他人。
A -- B -- C -- D
,而不是期望的 A -- D -- B -- C
。 - XedinUnknownD
,因此我们有 A - B - C - D
,目标是 A - D - B - C
。运行命令 git rebase -i HEAD~4
,并在编辑器中重新排序提交以达到 ADBC 的顺序,保存并退出。 - KazD
可能是任何一个提交。假设我们有 A - B - C
这样的一个分支,并且有一个提交 D
,它甚至不在这个分支中。我们知道它的 SHA 值。我们可以运行 git rebase -i HEAD~3
命令。在 A
和 B
的 pick
行之间插入一行新的 pick
命令,命令内容为 pick SHA
,其中 SHA
是所需的 D
提交的哈希值。它不必是完整的哈希值,只需要是缩短后的哈希值即可。git rebase -i
只会挑选在缓存区中由 pick
命令列出的提交记录;它们不必是原来列表中所列出的提交记录。 - Kazbreak
关键字(或者在第一行使用它,以在指定的提交(commit)之前插入一个提交)。 - SimonTbranch
上。按照以下步骤进行操作:
从您想要插入新提交之后的提交(在本例中为提交A
)创建一个临时分支:
git checkout -b temp A
进行更改并提交它们,创建一个提交,我们称之为N
:
git commit -a -m "Message"
git add
,然后执行git commit
)(如果有的话,可能需要使用-p
来保留合并,感谢一个已经不存在的评论 by ciekawy)
A -- N -- B -- C
git push --force
命令来更改远程代码库。 - escapecharactergit rebase temp branch -Xtheirs
。这对于在脚本中注入非常有帮助! - David Cgit rebase temp branch
之后,但在执行 git branch -d temp
之前,你只需要解决和暂存合并冲突,并发出 git rebase --continue
命令即可,无需提交任何内容等。 - Pugsleygit rebase --rebase-merges temp branch
,而不是git rebase -p temp branch
。 - undefined更简单的解决方案:
在结尾创建你的新提交,D。现在你有:
A -- B -- C -- D
然后运行:
$ git rebase -i hash-of-A
Git会打开你的编辑器,界面看起来是这样的:
pick 8668d21 B
pick 650f1fc C
pick 74096b9 D
将 D 移动到顶部,然后保存并退出
pick 74096b9 D
pick 8668d21 B
pick 650f1fc C
现在你将拥有:
A -- D -- B -- C
这里有一种策略可以避免在其他答案中所看到的rebase时进行“编辑hack”。
通过使用git rebase -i
,您可以获得自上次提交以来的提交列表。只需在文件顶部添加一个“break”,就会导致rebase在该点中断。
break
pick <B's hash> <B's commit message>
pick <C's hash> <C's commit message>
一旦启动,git rebase
将停在 "break" 点。
现在您可以正常编辑文件并创建提交。
然后,您可以使用 git rebase --continue
继续重塑。这可能会导致必须解决的冲突。 如果您迷失了方向,请不要忘记您始终可以使用 git rebase --abort
中止它。
此策略可概括为在任何位置插入提交,只需将 "break" 放在要插入提交的位置即可。
重写历史后,请不要忘记使用 git push -f
。其他人获取您的分支时通常会出现警告。
rebase -i
。这使得许多挑选操作更容易跟踪。 - rookie1024已经有很多好的答案了。我只想添加一个“不要变基”的解决方案,仅需4个简单步骤。
概要
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
解释
(注意:这种解决方案的一个优点是,直到最后一步时你非常确定结果没问题之前都不需要修改你的分支,因此你有一个非常方便的"预确认"步骤,可以进行A/B测试。)
初始状态(我假设你的分支名称为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)。
(两者选一)4-OK)最后,将master
的引用移动
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
。
A -- B -- C -- E -- F
,并且 B
和 E
是合并提交,会发生什么? - Umair Khan-m
选项。 - Romain Valeri假设提交历史是preA -- A -- B -- C
,如果你想在A
和B
之间插入一个提交,步骤如下:
git rebase -i hash-of-preA
Git将打开你的编辑器。内容可能如下所示:
pick 8668d21 A
pick 650f1fc B
pick 74096b9 C
将第一个 pick
改为 edit
:
edit 8668d21 A
pick 650f1fc B
pick 74096b9 C
保存并退出。
修改你的代码,然后 git add . && git commit -m "I"
git rebase --continue
现在你的Git提交历史是preA -- A -- I -- B -- C
如果遇到冲突,Git 会停在这个提交处。你可以使用 git diff
找到冲突标记并解决它们。解决所有冲突后,你需要使用 git add <filename>
告诉 Git 冲突已经解决,然后重新运行 git rebase --continue
。
如果想撤销变基,则使用 git rebase --abort
。
假设您要插入的提交由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
A
和B
之间的可视图形上双击-哦,等等,不对,现在是2023年,我们还没有那个功能。 - Nils Lindemann