我的一位同事检查了提交correct_parent
,根据correct_parent
进行了一些更改,然后以某种方式错误地提交了另一个错误的父提交rev wrong_parent
而不是correct_parent
(我不确定他是如何做到的那样)。让我们调用他的提交bad_commit
。
一大堆新提交基于bad_commit
,包括新的合并提交,所以它不仅仅是一个线性结构,更像是钻石。他们最终又被重新合并为一个分支。我们称之为bad_branch
。
我想使用正确的父提交bad_commit
重新创建correct_parent
,以及所有后续提交。
我不确定该怎么做。可能以某种方式git rebase
和--strategy ours
左右。请注意,这不仅仅是一个rebase,因为wrong_parent
和bad_commit
之间的差异不是意义上的,所以我不想将其作为补丁应用。
图片:
wrong_parent -> bad_commit (based on correct_parent) -> ...... -> bad_branch HEAD
我想:
correct_parent -> bad_commit (merge strategy: take bad_commit) -> .... -> fixed_branch
答案 0 :(得分:2)
这可以通过移植文件修复,使用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
现在假装“好父母”是“孩子”的父母:
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
你看到孩子得到了一个新哈希。那是因为提交是用适当的父级重写的。父母没有得到新的哈希,因为它没有改变。任何“孩子”的孩子也会被改写。
最后,只需清理:
rm .git/info/grafts
答案 1 :(得分:1)
从correct_parent
创建一个新分支,
and cherry根据wrong_parent
选择在另一个分支上发生的提交:
git checkout -b fix correct_parent
git cherry-pick wrong_parent..other_branch
感谢@poke提出建议!
答案 2 :(得分:0)
似乎是git rebase
的工作。
git checkout -b ok_branch <correct_parent>
-p --preserve-合并
重新创建合并提交,而不是通过重放合并提交引入的提交来展平历史记录。不保留合并冲突解决方案或手动修改合并提交。
这在内部使用--interactive机器,但明确地将它与--interactive选项结合使用通常不是一个好主意,除非你知道你在做什么(见下面的BUGS)。
git checkout -b replaced_branch <bad_branch>
git rebase --preserve-merges ok_branch
git branch -D ok_branch
完成这些更改后,您将
- correct parent [ok_branch] - bad commit - .... - HEAD [replaced_branch]
<强>更新强>
您可以找到usesul flag --onto
(参考https://git-scm.com/book/en/v2/Git-Branching-Rebasing#More-Interesting-Rebases)