Git Rebase 从带有 Squashed 合并的分支

Posted

技术标签:

【中文标题】Git Rebase 从带有 Squashed 合并的分支【英文标题】:Git Rebase from a branch with Squashed merges 【发布时间】:2021-12-14 07:13:40 【问题描述】:

假设我已经提交了我的dev 分支,

a
b
c

我向main 分支发出拉/合并请求,并打开了壁球合并选项。

所以main 分支现在看起来像,

merge from 'dev' to 'main'
squash: a, b, c

但我的源分支dev 仍然是三个单独的提交。当我在 dev 分支上执行 git rebase main 时,这可能是一个问题,尤其是当 main 分支塞满了其他开发人员的压缩合并时。

通常,我会 cherry-pick 我的提前提交到 dev_bak 分支。删除我当前的分支dev 并通过这样做重新发布它

git switch [any-branch]
git branch -d dev   // delete dev branch
git checkout -b dev // re-create dev branch
git rebase main     // do rebase
git push --force    // force push to remote to overwrite

然后将我的提前提交挑选回dev 分支。

所以我想知道是否有一种快速的方法可以做到这一点?或许是git rebase --force

谢谢!!

【问题讨论】:

【参考方案1】:

您最好的选择是不要对您不删除的分支使用 squash 合并。壁球合并丢弃了分支上的历史;无论如何,只有当您要删除该分支时才有意义。对于长时间运行的分支,最好创建一个合并提交,以便记录分支之间的关系。

因为 squash 合并不会记录合并了哪些提交,如果您继续使用分支,则需要手动跟踪。

如果您可视化您拥有的提交图以及您正在尝试创建的内容,那么您可以计算出要使用的变基命令 - 这不是“强制”变基,而是告诉 git 您想要保留哪些提交。

假设我们从这个开始:

... <--A <--B <--C <--D <--E <--F
                 ^              ^
               main            dev

然后你将 dev 压缩合并到 main(提交 DEF),并继续提交到 dev:

... <--A <--B <--C <--D <--E <--F <--G <--H
                  \                       ^
                   <-- DEF               dev
                        ^
                      main

你想要结束的是这个(提交 GR 和 HR 分别重新创建 G 和 H 的更改):

... <--A <--B <--C
                  \                      
                   <-- DEF <--GR <--HR
                        ^            ^
                      main          dev

git rebase 有一个三参数形式,我将其读作“从 old_base 重新提交提交到 new_base”:git rebase old_base tip --onto new_base(有些人更喜欢将 --onto new_base 放在首位,这真的没关系)。

所以在这种情况下,我们想要“将 F 到 H 的提交变基到 DEF 上”(因为 F 是我们压缩的最后一个提交):

git rebase F H --onto DEF

由于我们有一些分支指针,我们只需要查找 F 的提交哈希,就可以这样写:

git rebase F dev --onto main

【讨论】:

【参考方案2】:

首先,让我们可视化您的场景:

o---o---o-----S (main)
     \
      A---B---C (dev)

提交S 是将ABC 压缩为单个提交并将其应用于目标分支(又名“挤压合并”)的结果。

现在,您所指的问题是由于 S 与原始提交 ABC无关,即使它包含同样的变化。在 main 之上重定 dev 会导致合并冲突,因为 Git 会尝试在压缩的提交之上重新应用相同的更改。

您要查找的命令是 reset--hard 选项:

git switch dev
git reset --hard main

这将移动dev 分支以指向与main 相同的提交:

o---o---o-----S (main, dev)
     \
      A---B---C

提交 ABC 现在将变为 unreachable 并最终将被删除。

请注意,--hard 选项还将同步您工作目录中的文件以匹配您要重置的提交。这意味着当您执行此操作时,您的工作目录中任何未提交的更改都将被丢弃。在执行git reset --hard 之前,请确保将它们存储或提交到临时分支。

【讨论】:

以上是关于Git Rebase 从带有 Squashed 合并的分支的主要内容,如果未能解决你的问题,请参考以下文章

git rebase详解

Git-git rebase详解

Rebase - 功能分支合并到主分支的操作

图解 Git 基本命令 merge 和 rebase

GitBash教程 使用 git rebase合并commit

闲谈 git merge 与 git rebase 的区别