如何重新定位到已覆盖历史记录的分支?
How to rebase onto branch that has overwritten history?
假设我有分支 1
,提交 A
。
1: A
从 1,我创建了另一个分支,2
。
2: A
在 2
,我添加了一个提交。
2: A->B
然后在 1
上,我做了一些更改并 git commit --amend
,覆盖了 A
。
1: C
在 2
,我想要在 1
上进行这些新更改,并且只想将我在 B
上所做的更改应用到 C
上。但是,据我了解,git 会看到分支 2
有新的提交 A
和 B
,并尝试在 [=24] 之上应用这两个提交=].所以当我完成变基后,2
看起来像
2: C->A->B
当我真正想要的是C->B
。
处理这种情况的正确方法是什么?到目前为止,我处理这个问题的方法是从 1
创建一个新分支,然后从 2
中挑选提交 B
。但这似乎有点 hacky,而且当 2
有不止一个新提交时做起来并不是那么微不足道。
让我们用更传统的方式来展示它,看看发生了什么。
如果 A 是第一个提交,事情就变得复杂了,所以我将添加一个祖先 Z。
Say I have branch 1 with commit A.
Z - A [1]
From 1, I create another branch, 2.
Z - A [1][2]
On 2, I add a commit.
Z - A [1]
\
B [2]
Then on 1, I make some changes and git commit --amend, overwriting A.
这就是事情变得不稳定的地方。
C [1]
/
Z - A
\
B [2]
Git 从不 "overwrites" 提交。它不能。提交 ID 是提交内容及其所有祖先的校验和。 commit --amend
(以及 rebase
)所做的是创建新的提交并假装它一直都是那样。
但是旧的提交仍然存在。如果有任何东西以它为祖先,就像这里的分支 2,它将是可见的。
On 2, I want these new changes on 1 and want to just apply my changes from B onto C. However, from what I understand, git will see that branch 2 has new commits A and B, and try to apply both of these commits on top of C. So when I'm done rebasing, 2 will look like 2: C->A->B when what I really want is C->B.
这里的问题是因为 commit --amend
分支 1 和分支 2 不再有 A 作为共同祖先。现在是 Z。如果您尝试将 2 变基到 1,它会将 A 和 B 都放在 C 之上。
A1 - B1 [2]
/
C [1]
/
Z - A
\
B
虽然这可能有效,但也可能导致混乱的冲突。你必须使用更精确的 rebase 命令来让 Git 知道你真正想要什么。由于C实际上是A的重做,所以您真正想要的是2 after A.
上的所有内容
git rebase --onto 1 A..2
结果就是你想要的。
B1 [2]
/
C [1]
/
Z - A
\
B
(A 和 B 将不可见,它们最终将被垃圾回收。)
如果您认为这很复杂且充满危险,那是!
这就是为什么最好不要变基或修改你的"stable"分支,通常是master
。相反,只需使用普通提交或功能分支进行更大的更改。然后应用更新分支的正常过程。
假设我有分支 1
,提交 A
。
1: A
从 1,我创建了另一个分支,2
。
2: A
在 2
,我添加了一个提交。
2: A->B
然后在 1
上,我做了一些更改并 git commit --amend
,覆盖了 A
。
1: C
在 2
,我想要在 1
上进行这些新更改,并且只想将我在 B
上所做的更改应用到 C
上。但是,据我了解,git 会看到分支 2
有新的提交 A
和 B
,并尝试在 [=24] 之上应用这两个提交=].所以当我完成变基后,2
看起来像
2: C->A->B
当我真正想要的是C->B
。
处理这种情况的正确方法是什么?到目前为止,我处理这个问题的方法是从 1
创建一个新分支,然后从 2
中挑选提交 B
。但这似乎有点 hacky,而且当 2
有不止一个新提交时做起来并不是那么微不足道。
让我们用更传统的方式来展示它,看看发生了什么。
如果 A 是第一个提交,事情就变得复杂了,所以我将添加一个祖先 Z。
Say I have branch 1 with commit A.
Z - A [1]
From 1, I create another branch, 2.
Z - A [1][2]
On 2, I add a commit.
Z - A [1]
\
B [2]
Then on 1, I make some changes and git commit --amend, overwriting A.
这就是事情变得不稳定的地方。
C [1]
/
Z - A
\
B [2]
Git 从不 "overwrites" 提交。它不能。提交 ID 是提交内容及其所有祖先的校验和。 commit --amend
(以及 rebase
)所做的是创建新的提交并假装它一直都是那样。
但是旧的提交仍然存在。如果有任何东西以它为祖先,就像这里的分支 2,它将是可见的。
On 2, I want these new changes on 1 and want to just apply my changes from B onto C. However, from what I understand, git will see that branch 2 has new commits A and B, and try to apply both of these commits on top of C. So when I'm done rebasing, 2 will look like 2: C->A->B when what I really want is C->B.
这里的问题是因为 commit --amend
分支 1 和分支 2 不再有 A 作为共同祖先。现在是 Z。如果您尝试将 2 变基到 1,它会将 A 和 B 都放在 C 之上。
A1 - B1 [2]
/
C [1]
/
Z - A
\
B
虽然这可能有效,但也可能导致混乱的冲突。你必须使用更精确的 rebase 命令来让 Git 知道你真正想要什么。由于C实际上是A的重做,所以您真正想要的是2 after A.
上的所有内容git rebase --onto 1 A..2
结果就是你想要的。
B1 [2]
/
C [1]
/
Z - A
\
B
(A 和 B 将不可见,它们最终将被垃圾回收。)
如果您认为这很复杂且充满危险,那是!
这就是为什么最好不要变基或修改你的"stable"分支,通常是master
。相反,只需使用普通提交或功能分支进行更大的更改。然后应用更新分支的正常过程。