如何在合并分支之前将提交移回历史记录中的某个位置,同时保持分支完好无损?

How can I move a commit back to a location in history before a branch was merged while leaving the branch intact?

将分支合并到master后, 我意识到理想情况下我应该做一个小的承诺 在合并分支之前, 因为它与合并前的提交直接相关。 我试图澄清期望的结果是什么样的 在下面的简化示例中, 其中

当前分支结构:

A----B-C-D
    /
 X-Y

期望的结果是将 D 移动到 A 之后, 其余部分保持原样:

A-D----B-C
      /
   X-Y

选择所有提交并在 A 之后移动 D 后变基:

A-D-X-Y-B-C

删除 X 和 Y 并在 A 之后移动 D:

A-D-B-C

如何在我的历史记录中保留该分支? 在这里 rebase 是错误的工具吗? 我看过 cherry-pick, 但我不确定我将如何使用它来达到预期的结果。

万一重要, 分支不是来自主人, 但来自不相关的回购。 它添加了几个新文件 同时保留上一个仓库的提交历史。 这是一个本地回购 我是唯一的贡献者。

我不知道是否可以通过 git rebase -i 中的单个 运行 来实现。但你可以这样做:

git checkout A
git cherry-pick D
git merge Y # this will create kind-of a B', it won't be the same, though cause you brought D before it
git cherry-pick C

如果你喜欢这个结果,你可以考虑移动分支:

git branch -f master
git checkout master

你可能想做这样的事情:

git rebase -i --rebase-merges A

变基待办事项说明最初看起来像这样

label onto

# Branch branch-name/master
reset [new root]
pick X
pick Y
label branch-name/master

reset onto
merge -C pick B
pick C
pick D

按照标准 rebase 对底部重新排序:

reset onto
pick D
merge -C pick B
pick C

通过添加 --rebase-merges,您要求 Git 尝试重新创建任何现有分支并在发生变基时维护合并结构。

来自man pages:

--rebase-merges[=(rebase-cousins|no-rebase-cousins)]

By default, a rebase will simply drop merge commits from the todo list, and put the rebased commits into a single, linear branch. With --rebase-merges, the rebase will instead try to preserve the branching structure within the commits that are to be rebased, by recreating the merge commits. Any resolved merge conflicts or manual amendments in these merge commits will have to be resolved/re-applied manually.

By default, or when no-rebase-cousins was specified, commits which do not have <upstream> as direct ancestor will keep their original branch point, i.e. commits that would be excluded by git-log2's --ancestry-path option will keep their original ancestry by default. If the rebase-cousins mode is turned on, such commits are instead rebased onto <upstream> (or <onto>, if specified).

The --rebase-merges mode is similar in spirit to the deprecated --preserve-merges, but in contrast to that option works well in interactive rebases: commits can be reordered, inserted and dropped at will.

It is currently only possible to recreate the merge commits using the recursive merge strategy; Different merge strategies can be used only via explicit exec git merge -s <strategy> [...] commands.

查看相关的 Whosebug 主题 here