代码之家  ›  专栏  ›  技术社区  ›  taranion

Git:将多个存储库合并到一个目录中以保留历史记录的冲突

  •  0
  • taranion  · 技术社区  · 7 年前

    我有几个(约20个)Git存储库,它们的文件中没有重叠。我想将它们的主分支合并到一个(新)存储库中。

    经过一番阅读,我想出了以下的过程。

    1. 创建目标存储库(git init)并将其更改为目标存储库
    2. git remote add <name> <url>
    3. git fetch <name>
    4. git merge <name>/master --allow-unrelated-histories -m "Imported"
    5. git remote rm <name>
    6. 重复2-5次,直到合并所有存储库

    第一个存储库很好地合并了,历史也完好无损,但后来我遇到了合并冲突。

    E、 g.对于不同目录中具有相同名称的不同文件(我这边没有重命名):

    CONFLICT (rename/rename): Rename "Splittermond_CharGen_JFX/.project"->"BootloaderPlugin/.project" in branch "HEAD" rename "Splittermond_CharGen_JFX/.project"->"Splittermond_Zhoujiang/.project" in "splimo-common/master"
    

    E、 g.根据我在项目历史记录中移动的文件(树中留下的版本是最近的位置):

    CONFLICT (rename/delete): Splittermond_BuU/src/org/prelle/rpgframework/splittermond/buu/BestienUndUngeheuerPlugin.java deleted in HEAD and renamed to Splittermond_BuU/src/main/java/org/prelle/rpgframework/splittermond/buu/BestienUndUngeheuerPlugin.java in splimo-common/master. Version splimo-common/master of Splittermond_BuU/src/main/java/org/prelle/rpgframework/splittermond/buu/BestienUndUngeheuerPlugin.java left in tree.
    

    我认为Gits跟踪文件的能力可能是个问题,但我对这方面还比较陌生,不知道如何解决这个问题。

    感谢您的帮助或提示。

    [更新] 看起来我至少有两个存储库——虽然不再重叠——曾经是重叠的。我有一个git repo a,抱怨它删除了现在在repo B中的文件。我有一个repo B,曾经包含现在在repo a中的文件。 有没有办法合并两者,保留所有未删除文件的历史记录?

    3 回复  |  直到 7 年前
        1
  •  2
  •   max630    7 年前

    可能是重命名检测产生了错误的结果。然后你可以通过添加 -Xno-renames 到merge命令:

    ...
    git merge <name>/master --allow-unrelated-histories -m "Imported" -Xno-renames
    ...
    

        2
  •  1
  •   torek    7 年前

    我一点也不清楚发生了什么,我需要访问有问题的存储库和您的命令来重现这一点。然而,在考虑如何实现这一切时,需要记住两个关键点:

    • 在Git中,历史 提交(或者更明确地说,“提交就是历史”)。如果要保留历史记录,这意味着您要保留现有提交。
    • 合并 (动词形式, 要合并 从那个共同点开始 .

    正常合并有两个“边”。我给他们打电话 L --ours R 用于右侧、远程或 --theiRs . 它还有这个合并基提交,这是我们和他们在开始做自己的事情之前就开始的共同点。Git通过运行以下命令将“我们所做的”与“他们所做的”结合起来:

    git diff --find-renames B L   # base to left/local: what we did
    git diff --find-renames B R   # base to right: what they did
    

    path/to/new.txt 他们添加了相同的 但它有不同的内容,或者我们删除了 path/to/old.txt 他们修改了 路径/到/旧。txt文件 .

    当您使用 --allow-unrelated-histories 你在告诉Git,如果没有共同的承诺,Git应该 假装 有一个公共基,由一个完全没有文件的提交组成。也就是说 B 在两个 git diff 命令,Git应替换为 the empty tree ,因此每个文件都是新的。

    现在,你说:

    ... [一些相当多的]Git存储库在其文件中不重叠

    如果是这样,那么就不可能有 在两者中 L R

    此外,你 不能 如果历史记录确实不相关,则获取重命名/重命名或重命名/删除冲突,因为没有合并基,Git将使用空树 B 每一次。事实上,你得到这样一个冲突表明,历史 差异比较 从这个常见的合并基础上,可以在一侧找到重命名操作,在另一侧找到不同的重命名或删除。

    合并 作为形容词或名词,而不是动词)其树是通过使用 git read-tree -m 在所有适当的分支提示上建立合并索引,其提交是通过运行 git write-tree 然后 git commit-tree (带有适当的标志)。

    不过,我很犹豫是否要提供这个方法,因为如果它要起作用,你真的需要不相关的输入,而你看到的失败告诉我,你没有不相关的输入。

        3
  •  0
  •   taranion    7 年前

    幸亏 toreks 帮助我想出了以下解决方案:

    1. 使用初始化新存储库 git init
    2. git remote add <name> <url>
    3. git fetch <name>
    4. git merge <name>/master --allow-unrelated-histories -m "Reimported"
    5. git remote rm <name>
    6. git ls-files > /tmp/keep-these.txt
    7. git filter-branch --force --index-filter "git rm --ignore-unmatch --cached -qr . ; cat /tmp/keep-these.txt | xargs git reset -q \$GIT_COMMIT --" --prune-empty --tag-name-filter cat -- --all
    8. 对每个存储库重复步骤2-7

    添加的步骤6-7取自 new-repo-with-copied-history-of-only-current-tracked-files

    我希望这能有所帮助。