首页 > 解决方案 > 使用 Git Rebase 和导出修复合并冲突

问题描述

我遇到了一些与 git rebase 的合并冲突。

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

git add files
git commit "fixed merge conflicts"

然后继续

git rebase --continue

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

git rebase --abort 

那会删除所有提交吗?

标签: gitmergerebase

解决方案


根据jready 答案的评论,您真正的问题是您是否应该将原始提交链保存在某处/以某种方式。

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

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

如果您运行git checkout your-branch && git rebase origin/whatever,Git 必须复制commit J,将其转换为一组更改与其 parent G,并将这些更改应用于提交I(其中origin/whatever点)。复制J到 后J',它会尝试复制K到新的提交K',依此类推。在您解决任何冲突之后但在 Git “剥离名称”提交之前的最终结果L是:

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

的最后一步是从现在粘贴的位置git rebase删除名称,指向 commit ,并使其指向 commit —— rebase 制作的最后一个副本:your-branchLL'

                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)

your-branch在开始 rebase 之前,或者在 rebase 中间仍然指向 commit的任何时候L,您可以添加一个新名称来记住 commit 的原始哈希 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 命令(可能是另一个变基)覆盖,这些命令会像这样拉动标签,所以这是一种短期的权宜之计,如果您不喜欢,您可以使用它来恢复结果。

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

git reflog your-branch

会溢出所有这些,但是你得到的是你在每次提交中使用的一行摘要,并且当你使用时,git rebase你通常将原始的一行摘要从 commit 复制L到 commit L',因此很难分辨是哪一个是哪个。

尽管如此,一些ORIG_HEAD和 reflogs 的组合通常会让你在没有额外名称的情况下恢复。如果它让您更舒服,请使用额外的名称。我经常这样做:如果我正在处理feature/X,并且需要变基,我会创建feature/X.0然后变基。我最初的一系列提交现在可以作为点零版本使用。几天后,如果我需要做另一个变基,我创建feature/X.1然后变基。feature/X最新的也是如此feature/X.<number>,旧的也是如此,还有更多的旧的,直到我把它们收集起来并自己扔掉。


1从技术上讲,在 30 天内到期的提交正在使用expireUnreachable时间:这些提交是从引用的当前值无法到达的。Rebase 通常会做这种参考,所以默认的 30 天到期是你应该关注的。

(可访问的刷新日志条目默认为 90 天。)


推荐阅读