首页 > 解决方案 > Git:如何重新引入以前的删除或如何将父级合并到子级提交

问题描述

假设我有一个线性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只告诉我一切都是“已经是最新的”。

标签: gitgit-merge

解决方案


没有面向用户的命令可以做你想做的事。你可以完全做到这一点,有点手动。例如:

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 序列更多是为了说明。

git write-tree; git commit-tree; git merge --ff-only序列大致是git commit其自身实际工作的方式,但它git commit更精彩,并且不允许您指定单个父母。

另一种方法是使用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)

这对于一些未来的观众来说可能比奇怪的手动构建的合并更清楚。


推荐阅读