将Git子模块转换为子树后合并错误

时间:2013-01-08 22:15:06

标签: git merge git-submodules git-subtree

我有一个项目,我最初使用子模块来处理某些相关代码。事实证明,子模块并不适合这个项目(并且它们在实践中很难使用),因此我将每个子模块转换为子树(使用新的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/中创建新文件, 现在是主存储库的一部分,所有这些文件都与{{1}中仍然存在的文件冲突}}。

我找到的解决方法是在sub/之前使用rm -rf sub,这可以避免此问题。

我的问题是,是否有任何命令行开关我可以使用git pull说“覆盖工作目录中恰好存在的任何文件”?更好的是git merge查看现有文件内容的功能,如果内容与它要创建的文件完全相同,则禁止显示错误消息并继续。

更新:我已经创建了演示此问题的Git存储库,以准确显示我正在谈论的内容。重现:

git merge

这会导致错误消息

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

4 个答案:

答案 0 :(得分:9)

我知道您的问题特定于合并,但我在合并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步骤。当然,这有点迂回,如果你只有像你的例子那样只有一个子模块,也许不值得做。但是我发现在一个包含许多子模块的项目中工作非常节省时间。

另外,正如评论中指出的那样,如果您想避免对工作树进行更改,可以使用:

$ 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。它适用于您的示例,但是当涉及多个子模块时,我有意外的结果。不过,你可能会有更好的运气。

答案 1 :(得分:1)

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

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

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

答案 2 :(得分:1)

(警告:我从未使用过子树,我不知道你的实际回购是多么复杂,所以这些解决方案可能实际上并不适合你。)

从你的样本回购开始,我发现两个似乎都有效的解决方案,虽然它们产生不同的提交树:

  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)
    

    以下是生成的提交树:git commit tree - merge option

  2. 使用rebase而不是合并:

    ~/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)
    

    以下是生成的提交树:git commit tree - rebase option

答案 3 :(得分:0)

尝试了

  

git fetch --all

     

git reset --hard origin / master

但它不起作用。

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

git merge -s our our-master

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