git - 如何更改共同历史中的提交?

标签 git git-rebase

假设我有以下历史:

          --E  <- branch y
         /
A---B---C---D  <- branch x

我要修改commit B ,例如通过添加提交 B2并将其压缩成 B使用 git rebase -i .

历史应该是这样的:

          --E'  <- branch y
         /
A---B'--C'--D'  <- branch x

我的问题是:我该怎么做?

我尝试在 E 之后提交它或 D和 rebase ,但这会导致:

  --B'--C'--E'  <- branch y
 /       
A---B---C---D  <- branch x

一个解决方法是 rebase ED ;然后我可以去E' , 添加和压扁 B2 , 导致

             -E'  <- branch y
            /
A---B'--C'--D' 
 \
  --B---C---D    <- branch x

我可以在哪里让分支 x 指向 D' :

             -E'  <- branch y
            /
A--B'--C'--D'   <- branch x

几乎与我想要实现的目标相似,但感觉有点hacky,因为我手动移动了分支指针。 (在我的特殊情况下, rebase 是可以接受的,但我想知道一般情况。) 如果没有针对主要问题的简单解决方案,我想知道是否可以在不手动移动分支指针的情况下使用此解决方法。

附加信息:尚未推送相应的提交。

最佳答案

一个简单的解决方案是首先在其中一个分支上执行交互式 rebase ,进行我们的更改,然后将另一个分支 rebase 到新的 C':

git checkout branch_x

git rebase -i A
# mark commit B as edit, modify it, and complete the rebase

# rebase branch_y to be based on the new C' instead of C
git rebase --onto C' C branch_y

因为我们告诉原来基于Cbranch_y rebase 到新的C'上,所以我们恢复了原来的分支结构关于修改后的提交的分支。

请注意,我们需要知道 C 和新的 C' 的提交哈希值。在执行第二个 rebase 命令之前,我们必须在第一个分支上的交互式 rebase 之后查找它们。


另一种避免必须知道提交哈希值的解决方案是在此处执行保留 merge 的交互式 rebase 。请注意,这需要您先 merge 这两个分支。但是我们这样做只是为了 Git 保持分支关系,所以之后,我们可以再次摆脱那个 merge 。

所以要做到这一点,我们从任何分支开始, merge 另一个分支。然后我们执行一个保留 merge 的交互式 rebase 来修改提交 B(以我们想要的任何方式)。之后,Git 将正确重放这些分支(包括 merge ),所以我们以这段历史结束:

A -- B' -- C' -- D' ---- M'  ← branch
            \           /
             \         /
              E' ------

然后我们可以将分支指针移动到更新的提交 D'E',我们就完成了。

git checkout branch_x
git merge branch_y

# merge preserving interactive rebase
git rebase -p -i A
# mark commit B as edit, modify it, and complete the rebase

# we’re now on M', so move branch pointers to the new commits
git update-ref refs/heads/branch_y HEAD^2
git reset --hard HEAD^

历史现在应该是这样的:

A -- B' -- C' -- D'  ← branch_x
            \
             \
              E'  ← branch_y

不幸的是,我们必须在这里手动移动分支指针,因为我们一次只能 rebase 一个分支。所以因为我们已经为另一个分支重新设置了历史记录的基础(因为 merge ),我们仍然必须移动它的指针。所以我们只接受我们必须在这里手动重置分支(无论如何这并不是一件坏事)。

关于git - 如何更改共同历史中的提交?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38369257/

相关文章:

node.js - 从单个存储库发布多个包

git - 如何执行 Git "Do not rebase published commits"规则?

git - 如何从重新建立分支的分支中重新建立分支?

git - pull --rebase 后执行 git-hook

git - Ubuntu/DigitalOcean - 无法获取软件包以在全新安装时安装 git

如果子模块修改了文件,Git 不应 checkin

git - 对 git rebase 感到困惑

git pull --rebase 因冲突而失败,但 git push 有效

git - 在 Visual Studio 2015 中同步时使用 rebase

git - Vagrant 测试 Chef Recipe - 但如何处理私有(private) git