Git:如何重新引入以前的删除或如何将父提交合并到子提交中

Git: How to reintroduce former deletions or how to merge parent into child commit

假设我有一个线性 git 历史记录

A-B-C-...-X (HEAD)
          ↑
        master

现在我注意到,我删除了 C 中存在于 B 中的一些行,我想恢复这些行。可以手动复制所有内容或应用补丁。但我希望树看起来像

    -------
   /       \
A-B-C-...-X-Y (HEAD)
            ↑
          master

使更改更加明显。我尝试使用

合并
git checkout master
git merge --no-commit --no-ff B

git 只告诉我一切都“已经是最新的”。

没有 user-oriented 命令可以让您随心所欲。您 可以 完全做到这一点,有点手动。例如:

git diff <hash-of-A> <hash-of-B> | git apply
# make sure it looks right
git add <files>    # as desired
tree=$(git write-tree)
vim /tmp/message   # or other editor of choice
commit=$(git commit-tree -p HEAD -p <hash-of-B> -F /tmp/message $tree)
git log --graph --decorate --oneline $commit  # make sure you like it
git merge --ff-only $commit
# then clean up etc

您可以使用嵌套 $(...) 序列将其缩减为仅几个命令。

然而,大多数人更喜欢使用 git cherry-pick,也许还有 -x。请注意,git cherry-pick -n 可让您执行与 diff-and-apply 序列等效的操作,并可能使上述内容更加方便:我选择了 diff-and-apply 序列 more 进行说明。

git write-tree; git commit-tree; git merge --ff-only 序列大致就是 git commit 本身的实际工作方式,除了 git commit 更花哨,并且不允许您指定个人 parents。

另一种方法是使用 git checkout <hash-of-A>; git cherry-pick <hash-of-B> 进行新的提交 B',然后使用 git merge 合并这个新的 B' 提交。 (为你的 git merge 保存它的散列,或者在合并后删除的临时分支上执行此操作,这样你就不需要对原始散列 ID 大惊小怪。)结果看起来像这样而不是你绘制:

  ------B'------
 /              \
A--B--C--...--X--Y   <-- master (HEAD)

对于一些未来的观众来说,这可能比奇怪的 manually-constructed 合并更清楚。