目录变成子模块后合并

Merging after directory got turned into submodule

我发现在使用 git 子模块时,我经常遇到在包含给定子模块的提交与代表与普通目录相同代码的提交之间合并的问题。小复制示例:

# Create one project, to be used as a subproject later on
git init a
cd a
echo aaa > aa
git add -A
git commit -m a1
cd ..

# Create a second project, containing a as a normal directory initially
git init b
cd b
mkdir a b
echo aaa > a/aa
echo bbb > b/bb
git add -A
git commit -m b1

# Replace directory with submodule
git rm -r a
git submodule add ../a a
git commit -m b2

# Try to create branch from the pre-submodule state of affairs
git checkout -b branch HEAD^

这已经给出了一个错误:

error: The following untracked working tree files would be overwritten by checkout:
    a/aa
Please move or remove them before you can switch branches.
Aborting

为了避免报错,我先去初始化了所有的子模块:

# Create feature brach starting at version without submodule
git submodule deinit .
git checkout -b branch HEAD^
echo abc > b/bb
git commit -a -m b3

如您所见,功能分支与子模块完全无关,修改了一组不同的文件。这使得整个问题特别烦人。

# Try to merge the feature branch
git checkout master
git merge branch

这又失败了,出现了一条我不完全理解的错误信息:

CONFLICT (file/directory): There is a directory with name a in branch. Adding a as a~HEAD
Automatic merge failed; fix conflicts and then commit the result.

如果我在 git merge branch 之前执行 git submodule update --init,我会得到同样的错误。我在任何地方都没有看到任何 a~HEAD,无论是在我的目录树中还是在 git status 的输出中,它的内容如下:

On branch master
You have unmerged paths.
  (fix conflicts and run "git commit")

Changes to be committed:

    modified:   b/bb

Unmerged paths:
  (use "git add <file>..." to mark resolution)

    added by us:     a

如果我按照建议执行 git add a,我会收到另一个错误:

error: unable to index file a
fatal: updating files failed

如果我在合并之前执行 git submodules update --init,那么我可以成功执行 git add a。但如果我忘记这样做,然后在合并后尝试这样做,我会收到此错误消息:

Submodule 'a' (…/a) registered for path 'a'
Skipping unmerged submodule a

我该如何从这种情况中恢复过来? git merge --abort 以外的东西,因为我也想将它用于 git rebase 之类的东西,并且由于在某些情况下(不知道如何重现)我什至无法完全中止合并,而不得不进行硬重置。

我怎样才能首先避免它?是否有一些神奇的设置使 git 在合并期间对子模块与目录做正确的事情,这样我就不必手动 post-process 合并,它只修改与子模块无关的文件?

不,你不应该添加一个,合并不应该改变它。你应该运行是

git reset a

所以你忽略 "chage" 一个。

PS:显然 git 只是检查目录的存在,所以如果你

git submodule deinit a
rmdir a

合并前,会成功。不确定这是不是你想要的。

当我合并包含需要转换为子模块的文件夹的代码时,我遇到了类似的问题。

我通过使用 BFG --delete-folders 从新源代码中删除文件夹,并使用 git gc 清理存储库来解决它,然后我将 git rebase 没有任何冲突。