【问题标题】:Git: How to edit old commit with multiple descendant branches?Git:如何编辑具有多个后代分支的旧提交?
【发布时间】:2014-04-23 19:47:11
【问题描述】:

我的 git repo 的历史看起来像:

* (topic2) commit_11
* (topic1) commit_10
* commit_9
* commit_8
* (HEAD, master) commit_7
* commit_6
* commit_5
* commit_4 <- I wanted to edit this commit.
* commit_3

原来如此

git rebase -i commit_3

并在编辑器中将pick 替换为edit 以获取commit_4。 我更正了变量名中的一些拼写错误,然后

git add .
git commit --amend
(rename commit)
git rebase --continue

现在历史看起来像:

* (HEAD, master) commit_7.1
* commit_6.1
* commit_5.1
* commit_4.1 <- Edited commit.
| * (topic2) commit_11
| * (topic1) commit_10
| * commit_9
| * commit_8
| * commit_7
| * commit_6
| * commit_5
| * commit_4 <- Original commit.
|/
* commit_3

我想让我的历史像以前一样直截了当。我尝试了之前多次成功使用的方式

git checkout topic1
git rebase master

但在应用第一个补丁时会出现冲突。我手动解决了它们。但是当我尝试git rebase --continue 时,它告诉我“没有什么可提交的”。

如何处理这个问题,为什么会出现?

【问题讨论】:

  • 我认为您有点滥用版本控制。如果您在 commit_4 中犯了错误,请在新的提交中修复它,如果您需要在不同的分支中进行修复,请将其挑选到其他分支中
  • 如果这些都没有推送,也不是没有道理。
  • 这次变基期间当前的分支是什么?我想如果你在 master 中重新编辑,然后在 master 上 rebase topic*,历史将是线性的。
  • @Netch,如果我理解你的话,我的情况就像你说的那样。 (HEAD, master) 编辑前。 git rebase master 主题1
  • 拥抱非线性版本历史,您的问题将神奇地消失。 git 不是 svn。

标签: git git-rebase git-rewrite-history


【解决方案1】:

(我冒昧地修改了您的图表,以表明当您变基时,所有提交都会更改,即使内容没有更改。您的新提交集将具有与原件。)

这里最简单的解决方案是使用--onto。看看这个链接,从文本“这里是你如何移植一个主题分支”开始:git rebase

所以在你的情况下,它会是:

git rebase --onto commit_7.1 commit_7 topic1

换句话说,将提交从之后 commit_7 直到(包括)topic1,并将它们移植到commit_7.1。

不过,您可能仍会遇到必须手动修复的合并失败。

我建议您在执行此操作时,在 topic1 提交上创建一个额外的分支。称它为topic1old 什么的。如果变基不正确,这将更容易返回;您可以将您的 topic1 硬重置为该提交。

编辑:为什么简单的git rebase master 不起作用?

如果您不另外说明, git rebase 会假定您正在针对上游分支进行 rebase。

但是从我修改图表的方式可以看出,topic1 和 master 已经没有太多共同点了。如果您对 master 进行简单的 rebase,topic1 将尝试将您的所有提交 rebase 到 master 上的所有提交。这意味着你会得到类似的东西:

  • (topic1) commit_10
  • commit_9
  • commit_8
  • commit_7
  • commit_6
  • commit_5
  • commit_4
  • (HEAD, master) commit_7.1
  • commit_6.1
  • commit_5.1
  • commit_4.1
  • commit_3

现在 Git 很聪明,不会重复已经存在的提交。显然,如果您更改了 X、Y 和 Z,然后稍后的提交再次进行了这些更改,Git 将忽略稍后的提交,因为这些更改已经存在。

但是让事情变得棘手的是您对提交 4 的更改。结果是之后的所有提交都提交到不同的代码集。这留下了进行大量合并的潜在必要性。

使用 --onto 可以解决此问题,因为它允许您使用不同的基础。你是说:“我不关心 commit_4(因为我改变了它)也不关心 commit_5、_6 和 _7(因为我已经合并了它们,并且它们与我的主题分支中的基本相同)。所以从 commit_8 开始,将这些更改重新建立在我已经处理过的内容之上。”

【讨论】:

  • Kyralessa,您的解决方案完成了这项工作。但是谁能解释一下为什么这次简单的git rebase master 不起作用?
  • Kyralessa,感谢您的澄清。我猜git rebase master 的成功取决于对 commit_4 所做的更改。
猜你喜欢
  • 2013-12-30
  • 2020-08-13
  • 2018-11-10
  • 1970-01-01
  • 1970-01-01
  • 2011-11-02
  • 1970-01-01
  • 1970-01-01
  • 2019-11-24
相关资源
最近更新 更多