1

我有(或打算拥有!)这样的回购:

Master *-----*--*----------C---
        \                   \
Project1 \-*-------A----B----M2---A'--B'---
          \              \             \
Project2   \----------*---M1------------M2---

我想做合并M2我希望完全忽略AB。然后,我将手动(例如挑选)重新创建A'B'作为/如果有必要在来自 master 的新更改之上。

Project2 基于 Master,但合并了 Project1 的更改。

期望的结果:

  1. 我希望点M2在文件方面是C的相同副本。

  2. 我需要 Project1 有自己的线性历史,以便 Project2 可以从中合并。

上下文:Master 是 Drupal 的主要代码库。Project1 是我用来维护我希望与多个项目共享的特定补丁的分支。Project2(和许多其他)从 Project1 合并。

我考虑过:

  1. git merge -s recursive -X theirs mastertheirs问题在于 AFAIK 只有在发生冲突时才会喜欢它。因此,如果 A 中的更改不冲突,它将出现在M2处,这意味着 A' 将不完整。

  2. git revert B..A ; git merge C这会起作用,但会给我留下一个混乱而漫长的历史。

  3. git merge -s ours但似乎没有git merge -s theirs

  4. 我不想这样做,git reset --hard C因为这(我认为)会破坏将 Project1 合并到 Project2 的可能性。另一种方法是将 Project1 重新定位到 C 上,但同样,这意味着我无法合并到 Project2 中。

4

2 回答 2

2

我会建议你反对你的计划——你试图愚弄 git。Git 不喜欢被愚弄。你也在“伪造”你的历史。M2、A' 和 B' 都应该是一个提交——合并。

但是,如果您想继续,请执行以下操作:

git merge --no-commit C
rm -rf *
git checkout C .
git commit

如果您有任何要保留的 gitignored 文件,请在之前备份它们并在rm之后恢复它们。

或者,您也可以这样做(实际上更清洁)

git checkout C
git symbolic-ref HEAD refs/heads/Project1
git update-ref MERGE_HEAD C
git commit
于 2012-12-10T14:29:29.783 回答
1

这可以通过“管道”命令来完成:

$ git checkout Project1
$ git diff HEAD..master | patch -p1 
$ git add -A .
$ git commit-tree `git write-tree` -p master -p Project1 \
      -m "Merge to clean Master at v1.2"
0c5290081989cc28ff3977fbfe3951db7b7778b0
$ git reset --hard 0c5290081989cc28ff3977fbfe3951db7b7778b0

git diff HEAD..master它将告诉我如何在一个大补丁中从我所在的位置(B 和我想成为的位置(C)开始,并且补丁当然会应用它。

git add -A .会将工作树中的所有更改添加到索引中。

然后我们使用下一行为此创建一个合并提交:git-write-tree从索引创建一个新的树对象,并将其 SHA1 作为参数输出到git commit-tree,它为它创建一个提交,它有两个父级,即 Project1 的当前负责人(B)和 master ( C ),并给它一个合适的消息。

Git 将创建提交对象,但不会更新任何分支以使用此提交。最后一行告诉 git,我们希望将当前分支 Project2 推进(快速转发)到它生成的提交 SHA1。

如有必要,您可以从那里重新创建(例如,可以尝试使用cherry-pick)补丁A'和B'。

于 2012-12-10T14:57:29.523 回答