我有一个分支 A 和一个分支 B (以及其他一些分支)。
让我们说 A 的提交历史记录如下:
B 的提交历史记录:
基本上我想要的是“删除”提交所做的所有更改其他提交和将其他内容从分支C 合并到分支 B < / em>的
我希望分支 B 的工作树与分支 A 的工作树完全相同。
我如何实现这一目标?
答案 0 :(得分:14)
实现这一目标的一种方法是通过git reset
。在分支B
上执行
git reset --hard A
此后,分支B
指向A
的头部提交。 --hard
选项重置索引和工作树,以便将所有跟踪的文件重置为分支A
中的版本。 A
的旧头部提交已复制到.git/ORIG_HEAD
,以便撤消更改。
或者 - 虽然不在分支B
上 - 您可以删除分支B
并重新创建它:
git branch -d B # delete branch B
git branch B A # re-create branch B and let it point to the commit of branch A
除了第一个建议外,这将使索引和工作树保持不变。
答案 1 :(得分:5)
如果您希望分支B
看起来与分支A
完全相同。你可以做一个reset --hard
git checkout branch-B
git reset --hard branch-A
小心你会在这种情况下失去提交。你的分支-B看起来就像分支-A一样,无论对分支-B的提交是什么,在分支-A中都不存在,将丢失。此外,如果branch-B与其他人共享,则不建议执行此操作。
在这种情况下,您可以尝试在branch-B中恢复您不想要的提交
git revert <sha-of-"some other commit">
git revert <sha-of-"merge of other stuff from branch C (into branch B)">
第二次提交看起来像是一次合并提交,因此您可能也必须传递父级。
git revert <sha-of-"merge of other stuff from branch C (into branch B)"> -m1
答案 2 :(得分:0)
为完成操作,让我们添加这种非常简单的方法:
git branch -f branchB branchA
利用了git中的分支仅仅是指针这一事实。此命令仅将对一个分支的尖端提交的引用替换为另一个。无需进行复杂的结构更改即可构建您已经拥有的东西。
答案 3 :(得分:0)
我意识到(很晚才承认),OP实际上从未要求删除B的所有历史记录,而是更改,所以我的第一个答案和其他大多数答案一样以上确实实现了预期的工作树,但不幸的是,这是以牺牲分支B
的历史为代价的。
因此,我们在这里建议使用git commit-tree
(请参阅doc)保留所有完整历史记录并获得您想要获取的确切树的完整方法
# to be executed from branch B
git reset --hard $(git commit-tree -m "Reset to A" -p $(git rev-parse --abbrev-ref HEAD) $(git rev-parse A)^{tree})
说明
已分解的git commit-tree
命令:
git commit-tree -m <message> -p <parent> <tree>
<tree>
在这里需要成为分支A
的树,我们将通过$(git rev-parse A)^{tree}
来获得它。<parent>
必须指向B
的提示:$(git rev-parse --abbrev-ref HEAD)
git reset --hard
在B
返回的新提交上设置当前分支(git commit-tree
)。乍一看看上去很复杂,但是是个很好的工具。
答案 4 :(得分:0)
正如其他人所表明的那样,git reset --hard
确实会使分支 B 看起来与分支 A 完全一样。但是,这将删除 B 的历史记录。避免此问题的另一种方法是创建并应用补丁文件:
git checkout A
git diff B > /tmp/AtoB.patch # Generate changes needed to make B match the current branch A
git checkout B
git apply /tmp/AtoB.patch # Update files to match the state of A
git add -A # Track any deleted or newly created files
git commit -a -m "Make B match A" # Commit the changes
现在我们不是“重写历史”,所以当你推到起源时不会有争议。这种方法的好处是同步是 B 历史中的一个离散提交,可以随时恢复。但是请注意,来自分支 A 的提交历史记录在翻译中丢失了。
<块引用>顺便说一句:如果您收到有关二进制文件的错误,请将 --binary 标志添加到您的 diff 命令中,如下所示 git diff --binary B > /tmp/AtoB.patch