在孤儿分支之间合并/挑选樱桃

时间:2015-06-30 09:11:46

标签: git merge

我设法获得了一个孤儿分支的git repo。要重现它,你可以这样做(" subl code.txt"意思是编辑代码文件):

C:\g\orphanrepomerge> git init
C:\g\orphanrepomerge> subl code.txt
C:\g\orphanrepomerge> git add -A
C:\g\orphanrepomerge> git commit -m "added starting point (best fit for parent later)"
C:\g\orphanrepomerge> subl code.txt
C:\g\orphanrepomerge> git commit -am "simulate some dev in first branch"
C:\g\orphanrepomerge> subl code.txt
C:\g\orphanrepomerge> git commit -am "simulate some more dev in first branch"
C:\g\orphanrepomerge> git checkout --orphan second
C:\g\orphanrepomerge> git rm -rf .
C:\g\orphanrepomerge> md ./sub/folder | cd
C:\g\orphanrepomerge\sub\folder> subl code.txt
C:\g\orphanrepomerge\sub\folder> git add -A
C:\g\orphanrepomerge\sub\folder> git commit -m "initial copy of first branch"
C:\g\orphanrepomerge\sub\folder> subl code.txt
C:\g\orphanrepomerge\sub\folder> git commit -am "some dev originally in second"

所以这是:

  • master:initial commit => commit1 => commit2
  • 第二名:初始副本* => commit3

* ...副本在子文件夹中完成!

示例在git中看起来像这样:

C:\g\orphanrepomerge> git log --graph master...second
* commit 0a3c91a4e72c331514fd68618febcf721d161a82
| Author: Fabian Wetzel
|
|     some dev originally in second
|
* commit f9f4718294258daee50bd89859e0626ddb0fad40
  Author: Fabian Wetzel

      initial copy of first branch

* commit ae53574452997a4be674d2d33e3fe1a3cb2bb3e6
| Author: Fabian Wetzel
|
|     simulate some more dev in first branch
|
* commit c32f6417cf818f11844a9ffb569232d65b2d5229
| Author: Fabian Wetzel
|
|     simulate some dev in first branch
|
* commit 1d8aace9312b5c51848c9fdadeac8cac53a4e7ad
  Author: Fabian Wetzel

      added starting point (best fit for parent later)

我想做的是在两个方向采摘樱桃,它在某种程度上有效,但期望的结果是令人失望的:

C:\g\orphanrepomerge> git checkout second
C:\g\orphanrepomerge> git cherry-pick c32f6417cf818f11844a9ffb569232d65b2d5229
error: could not apply c32f641... simulate some dev in first branch
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'
C:\g\orphanrepomerge> dir -Recurse


    Directory: C:\g\orphanrepomerge


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----        29.06.2015     13:54            sub
-a---        29.06.2015     14:29         25 code.txt


    Directory: C:\g\orphanrepomerge\sub\folder


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        29.06.2015     13:55         30 code.txt

git将原始code.txt添加回根文件夹,而不是将更改实际合并到子文件夹中的code.txt中。我能理解为什么会这样做,但对我来说却是错的。

我不知何故需要在[second]的第一次提交中引入父级来追溯将orphan分支转换为真正的分支,但我不知道怎么做?!

1 个答案:

答案 0 :(得分:1)

最简单的方法是使用graft point

说明

那么,什么是嫁接点?使用移植点,您可以伪造提交的祖先。这可以用于各种目的,例如在特定提交之前删除存储库的历史记录。

我们如何使用它们?您可以通过编辑.git/info/grafts文件来定义嫁接点。语法非常简单,第一个哈希是您想要定义的父级的提交,以及所有后续哈希将是它的父级。使用全部哈希非常重要,否则嫁接点不会起作用。

来源:主要引入移植点以平滑从其他VCS到git的过渡,其中合并并不包含有关合并分支的信息(查看您,较旧的SVN版本)。

动作

在您的情况下,您可以使用移植点将您的孤儿分支的初始提交与您选择的父级连接起来。这是一个抽象的例子:

<initial orphan branch commit hash> <parent commit hash>

使用问题中的哈希值,如下所示:

f9f4718294258daee50bd89859e0626ddb0fad40 1d8aace9312b5c51848c9fdadeac8cac53a4e7ad

永久

如果您想永久更改,可以使用git filter-branch -- --all而不是依赖嫁接点。来自filter-branch documentation

  

此命令用于尊重.git/info/grafts命名空间中的refs/replace/文件和引用。如果您定义了任何移植物或替换引物,则运行此命令将使它们永久化。

-- --all附录只包含所有参考文献,因此您无需手动指定参考文献。

重要:这会使您的孤儿分支历史记录与分支的任何推送历史记录不兼容。一定要了解这一点的含义。