Git 更改父提交版本

Git change parent commit rev

我的一位同事检查了提交 correct_parent,根据 correct_parent 做了一些更改,然后以某种方式错误地使用另一个错误的父提交 rev wrong_parent 而不是 [=13] =](我不确定他是怎么做到的)。我们称他的提交为 bad_commit.

一大堆新的提交基于bad_commit,包括新的合并提交,所以它不是简单的线性结构,而是更像菱形。他们终于又重新合并到一个分支中。我们称之为 bad_branch.

我想用正确的父提交 correct_parent 以及所有后续提交重新创建 bad_commit

我不太确定该怎么做。可能以某种方式 git rebase--strategy ours 左右。请注意,这不仅仅是一个变基,因为 wrong_parentbad_commit 之间的差异并不完整,所以我不想将其作为补丁应用。

一张图片:

wrong_parent -> bad_commit (based on correct_parent) -> ...... -> bad_branch HEAD

我要:

correct_parent -> bad_commit (merge strategy: take bad_commit) -> .... -> fixed_branch

correct_parent 创建一个新分支, 并根据 wrong_parent:

挑选发生在另一个分支上的提交
git checkout -b fix correct_parent
git cherry-pick wrong_parent..other_branch

感谢@poke的建议!

似乎是 git rebase 的工作。

  1. 创建分支指向正确的父节点

git checkout -b ok_branch <correct_parent>

  1. 做一个 rebase 保存合并(参考 http://git-scm.com/docs/git-rebase

-p --preserve-merges

Recreate merge commits instead of flattening the history by replaying commits a merge commit introduces. Merge conflict resolutions or manual amendments to merge commits are not preserved.

This uses the --interactive machinery internally, but combining it with the --interactive option explicitly is generally not a good idea unless you know what you are doing (see BUGS below).

git checkout -b replaced_branch <bad_branch>

git rebase --preserve-merges ok_branch

  1. 删除临时分支

git branch -D ok_branch

进行这些更改后,您将拥有

- correct parent [ok_branch] - bad commit - .... - HEAD [replaced_branch]

更新

您可能会发现 usesul 标志 --onto(参考 https://git-scm.com/book/en/v2/Git-Branching-Rebasing#More-Interesting-Rebases

这可以通过嫁接文件修复,使用 git filter-branch.

永久保存

设置错误的回购:

git init
echo a > file && git add file && git commit -m "good parent"
echo b > file && git add file && git commit -m "bad parent"
echo c > file && git add file && git commit -m "child" file

这在 git log --oneline 中显示为

f6e3133 child
4dc60b6 bad parent
7b5da8a good parent

现在假设"good parent"是"child"的parent:

echo `git rev-parse @ @~2` > .git/info/grafts

并再次检查 git log --oneline

f6e3133 child
7b5da8a good parent

现在让它永久化:

git filter-branch

第三次检查git log --oneline

87b8fc8 child
7b5da8a good parent

你看到 child 有一个新的散列。那是因为提交是 re-written 和正确的 parent。 parent 没有得到新的散列,因为它没有改变。 "child" 的任何 children 也会被重写。

最后,清理一下:

rm .git/info/grafts