18

我有一个项目,我最初将子模块用于一些依赖代码。事实证明,子模块并不真正适合这个项目(而且它们在实践中很难使用),所以我将每个子模块转换为子树(使用新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/.

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

我的问题是,有没有我可以使用的命令行开关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
4

4 回答 4

11

我知道您的问题是针对合并的,但我在合并 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。它适用于您的示例,但是当涉及多个子模块时,我得到了意想不到的结果。不过,你可能会有更好的运气。

于 2013-01-21T23:03:41.070 回答
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
...
于 2013-01-25T23:32:21.603 回答
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 - 合并选项

  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)
    

    这是生成的提交树:git commit tree - rebase 选项

于 2013-01-26T18:56:12.703 回答
0

它试过了

git fetch --all

git reset --hard origin/master

但它不起作用。

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

git merge -s ours old-master

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

于 2013-01-26T09:38:29.133 回答