1

If you clone a git repo inside of another git repo (e.g. to install code for a library or plugin into the parent repo) it appears impossible to add the file content of that directory to the parent repo as a simple commit of files, unless you delete or move the child repo's .git directory first.

You might want to instead add the repo as a submodule, in which case git add submodule <child_repo_url> <child_folder> will add it as two files:

new file:   .gitmodules
new file:   child_folder

In which child_folder is not an actual folder, but a simple text file that contains a line like this:

Subproject commit 3ddea2d9a36dbdbf02f9f1897b713704300b0c34

And the .gitmodules file contains the info about the repo, allowing git to later check out the exact same commit from that repo and so reconstruct all the files without actually adding them to the parent repo.

But, if you don't want that because you do want to simply add the files and just do git add <child_folder> instead you will see this message:

warning: adding embedded git repository: child_folder
hint: You've added another git repository inside your current repository.
hint: Clones of the outer repository will not contain the contents of
hint: the embedded repository and will not know how to obtain it.
hint: If you meant to add a submodule, use:
hint: 
hint:   git submodule add <url> child_folder
hint: 
hint: If you added this path by mistake, you can remove it from the
hint: index with:
hint: 
hint:   git rm --cached child_folder
hint: 
hint: See "git help submodule" for more information.

This sounds like it has done what I want, and is warning you in case you didn't want that to happen. But in fact, it hasn't added the files.

Instead it has added the same child_folder file as the git submodule add, but not the .gitmodules entry which seems like a necessary partner for it, and neither of the two commands it suggests will actually work now, because of the action that the command has just taken.

The git submodule add command would have worked, if the previous command hadn't already added something to the git index called child_folder, so the command fails with 'child_folder' already exists in the index.

The second command I assume would work if the first command had done what I'd wanted, and allow you to undo that action, but instead it will say

error: the following file has staged content different from both the
file and the HEAD:
    child_folder

So it seems at some point, what I want to happen was the default, and this error message was added to help people who had done it by mistake. Now, it appears impossible to do this with a single command, and the old help message is out of date and unhelpful.

Previously, you could avoid this behaviour by being careful about using, or not using, a final / when using git add child_folder/ to get one behaviour or the other but at some point in git's history aronud version 1.6 this workaround appears to have stopped working and you now always get the behaviour I describe.

There seems to be no flags you can add to the command to specify that you know the subdirectory is a repo, and that you don't care. There is a flag --no-warn-embedded-repo the help for which says:

By default, git add will warn when adding an embedded repository to the index without using git submodule add to create an entry in .gitmodules. This option will suppress the warning (e.g., if you are manually performing operations on submodules).

If you ignore everything after the "e.g." then it sounds exactly what I want. But if you include the e.g. then I don't know why you would want to manually update submodules that don't exist in .gitmodules. Either way, it doesn't help. It does suppress the warning, but the action it takes remains the same.

My current workaround is to delete or move the .git folder from the child repo to a different location before performing the git add, but it seems like this should be a possible option to have as a preference setting or command line flag, or indeed be the default behaviour with the existing warning message as help for those who don't want that, and the existing flag for people who know that they're doing something that throws a warning, and don't care.

Am I missing a git command or option that would do what I want or is this just a bug in git?

  • See https://stackoverflow.com/questions/31769820/differences-between-git-submodule-and-subtree – Inigo Aug 05 '21 at 08:25

0 Answers0