8

A recent change in Git changed the way the .git directory is handled when using submodules. Instead of having one .git per submodule, everything is now in the "root level" .git directory (the one corresponding to the working copy including the submodules).

Then, in each submodule, a file is created which points to the new location of the .git directory.

In my project, I have the following .gitmodules file:

[submodule "tests/shared-tests"]
        path = tests/shared-tests
        url = git://github.com/roboptim/roboptim-shared-tests.git
[submodule "cmake"]
        path = cmake
        url = git://github.com/jrl-umi3218/jrl-cmakemodules.git

When I do git clone --recursive, I then obtain:

$ cat cmake/.git
gitdir: /home/moulard/profiles/default-x86_64-linux-ubuntu-12.04.1/src/unstable/roboptim/roboptim-core/.git/modules/cmake

I am currently using Git 1.8.1.5.

My questions are:

  1. Why did this behavior change? I don't see any obvious gain to this new strategy.
  2. How can I then move safely a working copy? (if I move my working copy, I get an error message telling me that the path to the broken gitdir is not a Git repository anymore)

Please note that this is not the same as the previous question Moving the parent directory of a git repository that contains submodules in the sense that I am sure this is not an issue related by the presence of an absolute path in my .gitmodules file.

Community
  • 1
  • 1
Thomas Moulard
  • 5,151
  • 2
  • 21
  • 28

2 Answers2

10

The .git/module organization dates back from git1.7.8 (December 2d, 2011):

When populating a new submodule directory with "git submodule init", the $GIT_DIR metainformation directory for submodules is created inside $GIT_DIR/modules/<name>/ directory of the superproject and referenced via the gitfile mechanism.
This is to make it possible to switch between commits in the superproject that has and does not have the submodule in the tree without re-cloning.

However, recent bug fixes have been included in 1.8.2.1 and 1.8.3 (April 22d, 2013):

"git submodule update", when recursed into sub-submodules, did not acccumulate the prefix paths.

So upgrading to the very latest git release could fix this issue.


Here, one possible solution (with the latest git 1.8.3, April, 22d 2013), is mentioned by the OP Thomas Moulard in the comments:

$ git submodule deinit -f . is working!
Then I can run git submodule init and the paths get fixed

This takes care if the (de)initialization steps (.git/modules)

It doesn't take care of the 'add' step which records the url of a submodule in the .gitmodules file: you still need to remove it manually within that file.

Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • actually I tried with the last release of Git and the HEAD of master but so far no luck unless there is a git command I am not aware of... – Thomas Moulard Apr 23 '13 at 08:56
  • @ThomasMoulard latest being 1.8.3 in your case? – VonC Apr 23 '13 at 08:58
  • @ThomasMoulard But... but-but-but (https://github.com/git/git/tree/master/Documentation/RelNotes), 1.8.3 is only 15 hours old. They did 3 other releases already? – VonC Apr 23 '13 at 09:02
  • Sorry, I misread the last version. I tried 1.8.2.1 the last real release, 1.8.3 is already in `RelNotes` but there is no tag for this one yet. In either cases even the HEAD of `master` branch is not helping here (commit 118f60ee) – Thomas Moulard Apr 23 '13 at 09:09
  • @ThomasMoulard o, just checking here ;) What about http://stackoverflow.com/questions/15483276/git-submodule-not-working-after-deleting/15504813#15504813? – VonC Apr 23 '13 at 09:11
  • alas, in my case: `git rm -rf cmake` produces: `fatal: Not a git repository: /home/moulard/profiles/default-x86_64-linux-ubuntu-12.04.1/src/unstable/roboptim/roboptim-core/.git/modules/cmake` (and the directory is still here). Basically `git` is totally stuck unless I go and edit files by hand to fix paths. – Thomas Moulard Apr 23 '13 at 09:14
  • @ThomasMoulard where do you do that `rm -Rf`? in `.git/module`? or in the parent repo working tree? – VonC Apr 23 '13 at 09:16
  • At the root level of the parent repo working copy. [and it is `git rm` not simple `rm`] – Thomas Moulard Apr 23 '13 at 09:30
  • @ThomasMoulard in that case, I would recommend a `git submodule deinit` instead of a `git rm`. And then you add again your submodule. It is in the same spirit of http://stackoverflow.com/questions/15483276/git-submodule-not-working-after-deleting/15504813#15504813, but using the very latest command of git 1.8.3: http://stackoverflow.com/a/16162000/6309 – VonC Apr 23 '13 at 09:33
  • Woosh, `$ git submodule deinit -f .` is working! Then I can run `git submodule init` and the paths get fixed. Thanks! Can you update your initial answer to incorporate `git deinit`? Then I will accept it. – Thomas Moulard Apr 23 '13 at 09:37
  • @ThomasMoulard Excellent. I have included that process in the answer for more visibility. – VonC Apr 23 '13 at 09:40
1

I successfully fixed my work copy after moving it elsewhere doing the following:

  • Updating the gitdir: path in superproject/path/to/submodule/.git file
  • Updating the worktree= path in superproject/.git/modules/path/to/submodule/config file

I don't know why git uses absolute paths there!

(Tested on git 2.0.1.563)

Jonathan
  • 331
  • 2
  • 6