git交互式变基挤压到下一次提交

ou6hu8tu  于 2023-01-28  发布在  Git
关注(0)|答案(6)|浏览(155)

在Git中,我可以使用交互式rebase来重写历史,这很棒,因为在我的特性分支中,当我探索不同的重构和方法来完成时,我用部分工作的代码进行了大量的提交。
我想在将分支重定或合并到master之前,将大量的提交压缩在一起。
有些提交是按照从第一个(顶部)到底部(最后一个)的顺序进行的

1. Initial commit on feature branch "Automatic coffee maker UI"
2. Add hot chocolate as product
3. Add tea as product. Products are now generic
4. Create in memory data store for adapter tests
5. Cry because I can't get entity framework to create a composite key. Integration tests broken.
6. Implemented composite key!!
7. All tests green and feature done!

假设我想保留提交3、4和7。
使用rebase我想“挤压”提交

  • 一加二等于三。
  • 4次入住
  • 五加六得七
  • 理想情况下 * 我会在交互式基础重建中
1. squash
2. squash
3. pick (contains the work of 1 & 2)
4. pick 
5. squash
6. squash
7. pick (contains the work of 5 & 6)

但这是向后的,因为挤压合并了一个提交和它之前的提交,我不知道如何使它向前挤压。
我是不是很难相处,我应该接受这行不通(我宁愿让它奏效),还是有办法做到这一点?
我调用这个命令

git checkout My-feature-branch
git rebase master -i

然后我编辑提交列表,并试图通过保存文件和编辑编辑器来完成它,这通常对我很有效。

jmp7cifd

jmp7cifd1#

如果可行的话,您还需要对提交进行重新排序,使保留的提交位于压缩的提交之前。
如果这不可行,因为你会得到你不想解决的冲突,就做吧

1. pick
2. squash
3. squash
4. pick 
5. pick
6. squash
7. squash

当挤压完成后,你可以编辑提交消息,让它包含你希望最终提交时包含的消息。非常简单。:-)
你甚至可以

1. pick
2. fixup
3. squash
4. pick 
5. pick
6. fixup
7. squash

那么我认为应该只启动一次提交消息编辑器,就像修复一样,在没有启动编辑器的情况下,前一个提交消息就被简单地获取了。
在squash上,当提交消息编辑器触发时,你也会同时得到两条提交消息,一条来自待压缩提交,另一条来自待压缩提交,所以你可以简单地删除不想保留的提交消息。

gg58donl

gg58donl2#

在交互式重定基过程中,确实可以将一个提交压缩到 following 提交中,并完全保留第二个提交的身份(包括作者、日期等)。
不过,该方法有些复杂,因此git rebase -i的原生支持仍然值得赞赏。
我将用aaaaaaa Abbbbbbb Bccccccc C这三个提交来演示,我们希望将A合并到B中,并保留B的身份:(该方法很容易推广到更多的提交)

  • git rebase -i aaaaaaa^
  • 修改编辑脚本,使其在提交B后停止并退出编辑器:
pick aaaaaaa A
edit bbbbbbb B
pick ccccccc C
  • 当变基在B之后停止时,恢复最近的提交 * 两次 *,然后继续:
git revert HEAD
git revert HEAD
git rebase --continue

由于恢复的是先前的状态,所有后续的提交都将干净地应用。BRevert "B"的序列在一起没有任何影响,但是其中的第一个提交带有提交B的完整标识(实际上,在这个阶段它仍然是**提交B)。

BRevert "B"可以被压缩在一起,形成一个空操作提交,将提交B的标识与一个单独的rebase -i --keep-empty aaaaaaa^一起向前传递。这是非常有用的,也是推荐使用的,可以防止假合并冲突,特别是在更复杂的情况下。但是我们在这里跳过这一步,只将提交放在一起。
现在重要的提交是Revert "Revert "B"",它将携带最初由B所做的所有更改。

  • 现在,再次移动rebase -i aaaaaaa^,使其经过BRevert "B",同时将B挤压到Revert "B"A中:
pick   bbbbbbb B
squash b111111 Revert "B"
squash a222222 A
squash b333333 Revert "Revert "B""
pick   c444444 C

由于BRevert "B"的顺序没有影响,您可以将任何提交移过它,同时只创建容易解决的合并冲突。

  • 当rebase因合并冲突而停止时,请使用git mergetool和一个可以自动解决小冲突的工具,让这些工具来解决。
  • 重定基会再次停止,让你编辑压缩提交的提交信息。根据你的喜好编辑。
  • git rebase --continue,你就完成了。
izkcnapc

izkcnapc3#

Vampire's answer是对的,但我想提供一个不同的视角,我认为这是你让自己变得过于紧张的地方:您可以从以下内容开始:
假设我想保留提交3、4和7。
但随后添加:

  • 一加二等于三。
  • 4次入住
  • 五加六得七

但这意味着你想1、2、3、4、5、6和7的 * 所有 (的内容)...只是不作为 * 单独的提交 。交互式rebase squash并不意味着"扔掉",甚至也不意味着"扔掉提交消息",它的意思是"结合"。如果动词是"结合"或"融合"或"混合"或诸如此类的话可能会更好。所以序列(pick,squash,squash)的意思是: 保留所有三个,同时按顺序应用它们,然后做出一个大的承诺。
如前所述,一旦Git将它们组合成一个大的提交,Git会给你另一个机会将三个组合提交消息编辑成一个大的提交消息。
当改基完成后,你没有保留任何原始提交,而是创建了新的提交。你的第一个新提交是如何组合的并不重要,重要的是最终的提交源代码是什么,以及你在一个大的提交消息中添加了什么。

oxcyiej7

oxcyiej74#

我要做的就是一个reset加上一个commit -C

git rebase -i origin/main # or some other commit

这会打开你的编辑器,我把它做成这样:

...
pick aafaa Merge me forward
edit bbfbb Into me
...

然后,当变基在bbfbb处停止时,执行

git reset --soft HEAD^
git commit --amend -C HEAD@{1} # could put an explicit commit here
git rebase --continue

也可以将其放入单个重定基待办事项列表中:

...
pick aafaa Squash me forward
pick bbfbb Into me
exec git reset --soft HEAD^ && git commit --amend -C HEAD@{1}
...
a9wyjsp7

a9wyjsp75#

要改进golvok's answer,如果您想“向前挤压”多个提交,可以执行以下操作:
1.(可选)如果您修改了未推送提交中的某个文件,并随后取消了对该文件的跟踪,请确保先隐藏或清除未跟踪的文件。
1.开始变基:

git rebase -i origin/destination_branch

1.用fixup标记第一次和最后一次要压缩的提交之间的所有提交,并将下面的exec命令放在目标提交之后:

pick a52ff17 Feature A added
pick b69a7d9 Feature B WIP
fixup da37b5a Feature B WIP
fixup 009557e Feature B WIP
pick 4857cdd Feature B added
exec git reset --soft HEAD^ && git commit --amend -C HEAD@{1}
pick 15ffacb Feature C added

给你,小菜一碟。

bvjxkvbb

bvjxkvbb6#

你想要的是:

1. pick
2. squash
3. fixup
4. pick
5. squash
6. squash
7. fixup

然后当新的组合提交出现在编辑器中时,删除选中提交的行并保留修复。生成的特性补丁应该有来自系列中最后一次提交的提交消息。

相关问题