【问题标题】:Merge error after converting Git submodule to subtree将 Git 子模块转换为子树后出现合并错误
【发布时间】:2012-12-22 21:28:54
【问题描述】:

我有一个项目,我最初将子模块用于一些依赖代码。事实证明,子模块并不真正适合这个项目(而且它们在实践中很难使用),所以我将每个子模块转换为子树(使用新的git-subtree 功能)。

在我的工作存储库中,我已成功删除每个子模块并将旧的子模块存储库添加为子树。这个没问题。

当我转到另一个克隆并尝试从第一个克隆中提取时,合并步骤中出现以下错误:

error: The following untracked working tree files would be overwritten by merge:
        sub/.gitignore
        sub/Makefile
        sub/README
        sub/src/main.c
        ... and so on for all files in sub/
Aborting

这似乎是因为sub/ 中的文件最初从未真正存在于主存储库中,并且当 Git 应用补丁更新 .gitmodules 时,它不会删除包含子模块文件的目录。在处理下一次提交时,Git 尝试在 sub/ 中创建 现在是主存储库一部分的新文件,所有这些文件都与 sub/ 中仍然存在的文件冲突。

我发现的解决方法是在git pull之前使用rm -rf sub,这样可以避免这个问题。

我的问题是,有没有可以与git merge 一起使用的命令行开关,上面写着“覆盖工作目录中碰巧存在的任何文件”?更好的功能是git merge 会查看现有文件的内容,如果内容与它要创建的文件相同,则取消显示错误消息并继续。

更新:我创建了演示此问题的 Git 存储库,以准确显示我在说什么。重现:

$ git clone https://github.com/ghewgill/q14224966.git
$ cd q14224966
$ git submodule init
$ git submodule update
$ git merge origin/branch

这应该会导致错误消息

error: The following untracked working tree files would be overwritten by merge:
    sub/Makefile
    sub/README
    sub/src/main.c
Please move or remove them before you can merge.
Aborting

【问题讨论】:

  • 你试过这个吗:goo.gl/z1XP9
  • @Efthymis:完整链接是stackoverflow.com/questions/1295171/…(请不要在此处使用 URL 缩短器)。我尝试了git merge -s recursive -X theirs origin/master 并发生了同样的错误。
  • 是的,这似乎是一个聪明的机智git merge。我渴望得到那份赏金。
  • 我赞成你的回答,因为这也发生在我身上:D

标签: git merge git-submodules git-subtree


【解决方案1】:

我知道您的问题是针对合并的,但我在合并 git 子模块时遇到了类似的问题。我认为这个解决方案可以解决您的问题,即使它没有直接解决合并问题。

我发现通过强行检查要合并的分支,然后返回 master,子模块一切正常。

要在您的示例中正常工作:

$ git clone https://github.com/ghewgill/q14224966.git
$ cd q14224966
$ git submodule init
$ git submodule update
$ git checkout -f origin/branch
$ git checkout master
$ git merge origin/branch

这很有效,因为它基本上是为您执行rm -rf 步骤。当然,这有点迂回,如果你只有一个子模块,就像你的例子一样,可能不值得做。但是我发现在一个包含许多子模块的项目中工作时,它可以节省很多时间。

此外,正如 cmets 中所指出的,如果您想避免对工作树进行更改,您可以使用:

$ git clone https://github.com/ghewgill/q14224966.git
$ cd q14224966
$ git submodule init
$ git submodule update
$ git reset origin/branch
$ git reset --hard master

它的工作方式大致相同,但避免了在此过程中检出其他文件。我没有机会在野外使用它,但它似乎是一种合理的方法。

还有$ git merge -s subtree origin/branch。它适用于您的示例,但是当涉及多个子模块时,我得到了意想不到的结果。不过,你可能会有更好的运气。

【讨论】:

  • 我花了一点时间才明白这一点,看看这个方法有多聪明。我现在注意到您可以用git reset origin/branch; git reset --hard master 替换结帐;这避免了除了想要的删除之外的所有工作树活动。
  • @jthill 你是对的。您可以通过使用 reset 来完全跳过工作树的内容。我会更新我的答案以反映这一点。谢谢!
  • 不幸的是,使用git reset 的第二个解决方案失败了,因为它丢弃了在创建分支后对master 分支(比如README)所做的任何更改。
  • 此外,第一个解决方案(使用checkout -f)将sub/.git 目录保留在原位,这将导致未来的混乱,除非它也使用rm -rf 明确删除。
【解决方案2】:

你不能让git-merge(或任何其他命令)强行破坏它认为它不知道的文件,不。 git 非常努力地不做任何事情完全不可逆转。

但是使用许多子模块,您可以使用git submodule foreach 使您的删除更容易和更安全:

$ git submodule foreach 'rm -rf $toplevel/$path'
Entering 'sub'
$ git merge origin/branch
Updating a231acd..6b4d2f4
Fast-forward
...

【讨论】:

  • 这使得rm -rf 的操作稍微容易一些,但它仍然是相同的解决方案。
  • 唉,是的。但是您将不得不针对这种情况做一些特殊的事情,所以,不妨做最简单的事情
【解决方案3】:

(警告:我从未使用过子树,而且我不知道您的实际存储库有多复杂,因此这些解决方案实际上可能不适合您。)

通过使用您的示例存储库,我发现了两种似乎都有效的解决方案,尽管它们产生了不同的提交树:

  1. 使用git merge -s resolve origin/branch

    ~/q14224966[master]> git reset --hard origin/master
    HEAD is now at a231acd add submodule
    ~/q14224966[master]> touch other.c && git add . && git commit -m "New commit."
    [master bc771ac] New commit.
     0 files changed
     create mode 100644 other.c
    ~/q14224966[master]> git merge -s resolve origin/branch 
    Trying really trivial in-index merge...
    error: Merge requires file-level merging
    Nope.
    Trying simple merge.
    Simple merge failed, trying Automatic merge.
    Adding sub/Makefile
    Adding sub/README
    Adding sub/src/main.c
    Merge made by the 'resolve' strategy.
     .gitmodules    | 3 ---
     sub            | 1 -
     sub/Makefile   | 1 +
     sub/README     | 1 +
     sub/src/main.c | 1 +
     5 files changed, 3 insertions(+), 4 deletions(-)
     delete mode 160000 sub
     create mode 100644 sub/Makefile
     create mode 100644 sub/README
     create mode 100644 sub/src/main.c
    ~/q14224966[master]> ls
    README   main.c   other.c  sub/
    ~/q14224966[master]> cd sub/
    ~/q14224966/sub[master]> ls
    Makefile  README    src/
    ~/q14224966/sub[master]> git status
    # On branch master
    # Your branch is ahead of 'origin/master' by 5 commits.
    #
    nothing to commit (working directory clean)
    ~/q14224966/sub[master]> cd ..
    ~/q14224966[master]> git status
    # On branch master
    # Your branch is ahead of 'origin/master' by 5 commits.
    #
    nothing to commit (working directory clean)
    

    这是生成的提交树:

  2. 使用变基而不是合并:

    ~/q14224966[master]> git reset --hard origin/master 
    HEAD is now at a231acd add submodule
    ~/q14224966[master]> touch other.c && git add . && git commit -m "New commit."
    [master ae66060] New commit.
     0 files changed
     create mode 100644 other.c
    ~/q14224966[master]> git rebase origin/branch 
    First, rewinding head to replay your work on top of it...
    Applying: New commit.
    ~/q14224966[master]> ls
    README   main.c   other.c  sub/
    ~/q14224966[master]> cd sub/
    ~/q14224966/sub[master]> ls
    Makefile  README    src/
    ~/q14224966/sub[master]> git status
    # On branch master
    # Your branch is ahead of 'origin/master' by 4 commits.
    #
    nothing to commit (working directory clean)
    ~/q14224966/sub[master]> cd ..
    ~/q14224966[master]> git status
    # On branch master
    # Your branch is ahead of 'origin/master' by 4 commits.
    #
    nothing to commit (working directory clean)
    

    这是生成的提交树:

【讨论】:

  • 我尝试使用merge -s resolve,但如果子模块中的文件仍然存在(确保以git reset --hard origin/master && rm -rf sub && git submodule update 开头),则此方法不起作用。
【解决方案4】:

试过了

git fetch --all

git reset --hard origin/master

但它不起作用。

您可以使用“我们的”合并策略:

git merge -s ours old-master

您也可以使用 git-stash 保存更改,然后 git-stash apply 来恢复它们。

【讨论】:

  • 使用merge -s ours 根本没有进行合并,也没有解决问题。
  • 是的,这是一个您无法合并的问题:D 但您是否尝试过存储?
  • 不幸的是,存储没有帮助,因为您在取消存储时仍然必须进行某种类型的合并。
猜你喜欢
  • 2015-03-28
  • 1970-01-01
  • 1970-01-01
  • 2015-07-31
  • 2020-03-14
  • 1970-01-01
  • 1970-01-01
  • 2019-06-07
  • 2012-05-03
相关资源
最近更新 更多