How to make an existing directory within a git repository a git submodule

Doron Behar picture Doron Behar · Apr 3, 2016 · Viewed 28k times · Source

I'm very confused about git-submodules.

Basically my problem is that I can't make git understand that ~/main-project/submodule is a submodule.


I have good experience with git submodules:
in my dotfiles repository I created the .gitmodules file in ~/dotfiles-repo and I added there paths and urls. Since then, If I make changes to the files within the submodules and run git status, I'd get something like like: .vim/bundle/auto-complete (new commits) # in red

I created the .gitmodules file in ~/main-project but:

  • If I make changes to ~/main-project/submodule and even push the changes, I don't get a similar response like <submodule> (new commits) # in red when running git status in ~/main-project. I just get the changes that were made in those directories
  • When I hit the folders' links at github for these directories it's not directing me to the repositories themselves but I stay in the same repository.

    1. Maybe I'm missing the whole point. What are the main features of submodules?
    2. Why does git understands the submodules in the dotfiles repo but not in my other repo?
    3. Is it because I have already told git to add the files inside ~/main-project/submodule to the index?

I've read this question which led me to this answer But I'm not sure I need git-subtree. I don't want to do things that might do changes hard to be revert.

Edit: This suggested duplicate-solution didn't work either, I recieved an error that Updates were rejected because the remote contains work that you do not have locally. It seems that @GabLeRoux practically told me to push <repo-A> to the url of <repo-B>.

Answer

Doron Behar picture Doron Behar · Apr 3, 2016

Use git submodule absorbgitdirs

This is what the docs state this command does:

If a git directory of a submodule is inside the submodule, move the git directory of the submodule into its superprojects $GIT_DIR/modules path and then connect the git directory and its working directory by setting the core.worktree and adding a .git file pointing to the git directory embedded in the superprojects git directory.

So instead of starting all over as suggested in the previous answers by @DomQ and myself, one can just add run the following:

  1. Without removing from the index the submodule, Add the submodule's url to .gitmodules and to .git/config with
    git submodule add <url> <path>
  2. Move the submodule's $GIT_DIR directory (.git in regular repositories) to .git/modules/<path> with
    git submodule absorbgitdirs <path>

Original answer - pre v2.12.0

git submodule absorbgitdirs was introduced only in v2.12.0-rc0 (see commit).

The Solution is quite simple. It was extracted from here.

  1. git rm submodule-dir
    This will delete all the files that git was tracking after in submodule-dir
  2. rm -rf submoduledir
    This will delete all the other files that might have been left in submodule-dir because git ignored them.
  3. Now, we have to commit in order to remove the files from the index:
    git commit
    After the commit, we cleaned the files that git followed and didn't followed in submodul-dir. Now it's time to do:
  4. git submodule add <remote-path-to-submodule>
    This will re-add the submodule but as a true submodule.
  5. At this point it might be a good idea to check .gitmodules and see if the submodules have been added successfully. In my case I already had an .gitmodules file so I had to modify it.