如何在不丢失提交历史记录的情况下进行合并?

How do I merge without losing commit history?

所以这是一个大问题。我创建了如下所述的分支 change-branch,我需要将 1.3.6 和 1.4.1 的更改合并到这个分支中。现在的问题是我想有选择地合并更改。我不希望从 1.3.6 到 change-branch 的所有更改。我该怎么做?

这是结构

master
|- track1
|- track2
|---|- msr-657
|---|---|--1.4.1
|---|---|--change-branch
|- track3
|---|-- 1.3.6

您有四种方法:使用带有 --no-commit 标志的 merge 命令,在 merge 之后使用 revert,选择性 rebase,或者使用 cherry-pick.

--no-commit 合并可能是保留历史记录的最佳方式,但它会带来更多工作,因为您需要在提交之前手动回滚更改。

另一种选择是 merge,然后有选择地 revert 使用 git revert 进行更改。不过,这只会让历史变得更加混乱。

如果您不关心 "pure" 的历史记录,您可以简单地使用 rebase,但这只有在您尚未将您的更改推送到公共存储库 (如果您正在与其他人一起工作)或者您从一个废弃的分支机构进行变基。你会做这样的事情:

git rebase --interactive master 1.3.6

这会 rebase 您从 1.3.6 到 master 的更改,但首先会让您选择保留、编辑或忽略哪些提交。我很确定它会删除您正在从中执行 rebase 的任何分支,因此您应该在 rebase 之前在与 1.3.6 相同的位置创建另一个丢弃分支,然后创建 master 指向与throw away 分支相同的提交,然后最后删除throw away 分支。

使用 cherry-pick 允许您有选择地合并提交,但无需明确记住双亲。如果 1.3.6 分支保留在原始 repo 中,那么没有两个合并父项并不是什么大问题,因为您仍然在某处有历史记录,并且 cherry-pick 可以自动引用提交号说明。这会产生不纯的历史,就像选择性 rebase 所做的那样。

最后,这取决于您是否保留在 1.3.6 分支附近以及您希望您的历史记录最终看起来如何。

git cherry-pick最简单。你可以 git cherry-pick 任何你想要的提交到当前的 HEAD 中。您也可以尝试 git cherry-pick A..B 来挑选从 A 的 child 到 B.

的所有提交

git rebase 也足够强大来完成这项工作,但它有点棘手和令人困惑。