【问题标题】:Git: Is there a way to re-merge two commits on the same branch (FF) to a new branch?Git:有没有办法将同一分支(FF)上的两个提交重新合并到一个新分支?
【发布时间】:2015-05-22 11:13:09
【问题描述】:

我正在做一个小组项目,在进行了一些更改并推送到原点之后(称为此提交 A),另一个人似乎强制推送了他们的更改,从而恢复了我的提交(称为此提交 @987654322 @)。

在我推送之前,我们有这样的事情:

A (master)
|  B (their-master)
|  |
| /
Z (origin/master)

我推后,我们得到

   B (their-master)
   |
A (origin/master, master)
| /
Z

他们拉取我的提交,还原它并推送

B (origin/master, their-master)
|
A (master)
|
Z

我在不知不觉中拉到了

B (origin/master, master, their-master)
|
A
|
Z

我想在A 创建一个新分支(例如“re-merge”),将B 提取到新分支以手动解决合并冲突。然后将其合并回 master,这样我们就可以保留其他人的更改并绕过强制提交。

                                     D (origin/master, master, re-merge)
   C (re-merge)                      | \
   |                                 |  C
B (origin/master, master)    -->     B  |
| /                                  | /
A                                    A
|                                    |
Z                                    Z

有没有办法做到这一点,而无需在A 建立分支并手动比较文件以找到我想要保留的内容?这将迫使我放弃主分支,因为B 中的强制更改现在似乎被认为是从A 快速转发。除了其他从事无关事物的人也致力于掌握。

谢谢。

【问题讨论】:

  • 您绘制的内容(B 指向 A 作为其父项)不是强制推送。如果您最近的更改在提交A 中,听起来更像是您的合作者决定revert 您的工作(全部撤消)然后可能进行其他更改并将结果作为单个提交推送@ 987654336@。然而,在你的文本的其余部分,你让它听起来像 commit A 是一个常见的基本提交,你有一个现在隐藏的提交 A2,而 commit B 是协作者的提交;这确实可能是强制推动的结果。但是你仍然会在你的 repo 中有你的提交;你可以合并或变基。
  • 啊哈,我知道我有点不清楚(我真的不知道我在说什么)。有一个共同的基本提交Z,这是我们单独工作的内容,但我在推送B 之前提交并推送了A。你可能是对的,他们在他们的 pull/merge/whatever 中恢复了我的提交并推动了它。由于我从服务器中提取了B,我看不到如何重新设置基础,或者是否可以将父级重新设置为子级(因为我的树中的B 正式是A 的子级)?
  • 如果他们恢复了你的工作,你必须重新申请。这相对容易:只需使用git cherry-pick。根据修改后的图表查看下面的答案。

标签: git merge branch


【解决方案1】:

他们所做的可能是保存某些文件的版本(可能是所有有问题的文件),然后根据您的提交重新确定他们的工作,复制他们保存的文件版本,从而恢复您自己的工作(没有使用实际的git revert,但仍然完全没有共享工作的想法:-))。

你是正确的,你不能只是合并,因为你的提交 A 已经包含在当前提交的祖先中。

不过,不合并也很容易恢复。你想要的是让 git 看看你在提交 Z 和提交 A 之间做了什么:

$ git diff <rev-id-for-Z> <rev-id-for-A>

或者,因为您的HEAD 提交是B,所以HEAD~1(又名B~1 B^ 又名HEAD^ 等)是A,而HEAD~2Z

$ git diff HEAD~2 HEAD~1

然后取那个差异——好吧,也许是那个差异的一部分;如果需要,我们会尝试——并将其应用到当前工作树并根据结果进行新的提交:

$ git diff HEAD~2 HEAD~1 | git apply && git commit

有一个命令可以为您完成这一切:git cherry-pick。您将cherry-pick 指向一个特定的提交,它会将该提交与其前任进行比较,将生成的差异应用于您当前的工作树(如果可以的话),并使用一条提交消息提交结果,说明这是一个樱桃选择其他提交。

如果您想要不同的提交消息,您可以git commit --amend 结果,或者使用-n--no-commit 选项告诉cherry-pick 不要提交(这也允许工作树已经进行了其他更改)。

如果樱桃挑选不干净——例如,如果需要手动合并——你将不得不再次做一些清理工作。或者,您可以自己运行 git diff ... | git apply,在这种情况下,您可以限制文件集 diff-ed:

$ git diff HEAD~2 HEAD~1 -- path1 path2 | git apply

等等。

(注意,顺便提一下,与 diff-and-apply 不同,cherry-pick 可以直接访问提交图。因此它可以自动执行合并类型工作,使其比仅仅应用补丁更智能。差异文本留下了足够的apply 使用其 -3 选项执行相同操作的线索,但您必须指示 apply 执行此操作。最后,作为旁注,当您发现自己在执行某个提交的父级与那个的 git diff 时提交,这只是git show 的差异部分,所以只要您所做的任何事情都容忍“前导文本”,实际上您可以在目标提交上使用git show,而不是其父级与但我认为这不像 diff-pipe-to-apply 序列那样清晰,这就是我以这种方式说明它的原因。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-04
    • 2016-03-23
    • 2019-03-11
    • 2011-11-02
    • 2022-11-09
    • 1970-01-01
    • 2013-04-01
    相关资源
    最近更新 更多