使用 Git Rebase 和导出修复合并冲突

Fixing Merge Conflicts with Git Rebase and Exporting

我 运行 与 git 变基发生了一些合并冲突。

我的问题是,如果我解决了冲突,我是否会做这样的事情:

git add files
git commit "fixed merge conflicts"

然后继续

git rebase --continue

我的另一个问题是如果我搞砸了,我可以做吗

git rebase --abort 

这会删除所有提交吗?

git rebase --abort 将完全退出变基,实质上将您的存储库恢复到您开始 rebase 之前的时间点。唯一丢失的提交将是 git rebase 创建的全新提交(因为 git rebase 重播 您的原始提交,从而形成新的提交)。

无论您是否中止,都不会触及原始提交。

基于 on ,你真正的问题是你是否应该在某处/以某种方式保存你的原始提交链。

Rebase 在某种基础层面上是通过复制来工作的(因为提交永远无法更改——这包括它们的向后链接)。分支名称只是指向一些特定的提交。如果我们将提交绘制为图中的节点,我们将看到如下所示:

...--F--G--H--I   <-- origin/whatever
         \
          J--K--L   <-- your-branch

如果您运行 git checkout your-branch && git rebase origin/whatever,Git 必须复制 提交J,将其变成一组更改与其父 G 对比,并将这些更改应用于提交 I(其中 origin/whatever 点)。将 J 复制到 J' 后,它会尝试将 K 复制到新的提交 K',依此类推。在您解决任何冲突之后但在 Git "peels the name off" 提交 L 之前的最终结果是:

                J'-K'-L'  <-- HEAD
               /
...--F--G--H--I   <-- origin/whatever
         \
          J--K--L   <-- your-branch

git rebase 的最后一步是从现在粘贴的名称 your-branch 中删除指向提交 L 的名称,并使其指向提交 L'—rebase 的最后一个副本:

                J'-K'-L'  <-- your-branch (HEAD)
               /
...--F--G--H--I   <-- origin/whatever
         \
          J--K--L   [abandoned]

如果您使用 git rebase --abort 而不是继续,Git 只会放弃复制的链,留下名称 your-branch 仍然指向 L:

                J'-K'-L'  [abandoned]
               /
...--F--G--H--I   <-- origin/whatever
         \
          J--K--L   <-- your-branch (HEAD)

在你开始 rebase 之前,或者在 rebase 中间任何时候 your-branch 仍然指向提交 L,你可以添加一个新名称来记住提交的原始哈希 ID L:

                J'-K'  <-- HEAD
               /
...--F--G--H--I   <-- origin/whatever
         \
          J--K--L   <-- your-branch, extra-name

你可以用 git branch extra-name your-branch 来做。这样,在你完成 rebase 之后,假设你完成了它,你最终会得到:

                J'-K'-L'  <-- your-branch (HEAD)
               /
...--F--G--H--I   <-- origin/whatever
         \
          J--K--L   <-- extra-name

没有这样做,因为秘密地,git rebase设置了一个特殊的名字,ORIG_HEAD,以记住你的分支名称在哪里是在它把它从 L 上拉下来并粘贴到 L' 之前。但是名称 ORIG_HEAD 将被您以后使用的任何其他 Git 命令(可能是另一个 rebase)覆盖如果您不喜欢结果,可以恢复。

您的 Git 还在分支的 reflog 中记录了分支名称的先前值,即 your-branch 用于指向提交 L 而不是 L'。这些 reflog 条目持续 30 或 90 天。1 不过它们不是最容易使用的东西:

git reflog your-branch

会溢出所有的,但是你得到的是你在每次提交中使用的单行摘要,而当你使用git rebase时,你通常会从提交[=中复制原始的单行摘要26=] 提交 L',所以很难分辨哪个是哪个。

不过,ORIG_HEAD 和引用日志的某些组合通常可以让您在没有额外名称的情况下恢复。如果可以让您更舒服,请使用额外的名称。我经常这样做:如果我在 feature/X 上工作并且需要变基,我创建 feature/X.0 然后再变基。我的原始提交系列现在可以作为点零版本使用。几天后,如果我需要再做一次变基,我会创建 feature/X.1 然后再变基。所以 feature/X 是最新的,feature/X.<number> 是旧的,还有更多旧的,直到我自己收集起来扔掉。


1从技术上讲,那些在 30 天内过期的正在使用 expireUnreachable 时间:这些是 无法访问的提交 从引用的当前值。 Rebase一般都是做这种引用,所以默认的30天到期是你要注意的。

可访问的 Reflog 条目默认为 90 天。)