Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I init submodules nested in a subtree?

Apparently, adding a subtree of a repository that has submodules will break git submodule init. Here is a script which reproduces the problem:

#!/bin/sh
set -ex

mkdir submod
cd submod
git init
touch foo
git add foo
git commit -asm "This is a submodule"
cd ..

mkdir subtree
cd subtree
git init
git submodule add `realpath ../submod` submod
git commit -asm "This has reference to submodule"
cd ..

mkdir top
cd top
git init
touch bar
git add bar
git commit -asm "Dummy commit so HEAD resolves correctly"
git subtree add --prefix=subtree `realpath ../subtree` master

# This fails!
git submodule init

What this script is doing is:

  1. Create a repo submod
  2. Create a repo subtree that has a submodule reference to submod
  3. Create a repo top that has a subtree reference to subtree

Upon further consideration, it is clear what the problem is: the subtree mechanism has added subtree's submodule reference to submod to the tree, but the .gitmodules metadata remains in subtree/.gitmodules, not the top-level .gitmodules, which means that git submodule init fails. If we copy the contents of subtree/.gitmodules to .gitmodules, adjusting all the paths accordingly, that solves the problem...

[submodule "submod"]
    path = subtree/submod
    url = /Users/ezyang/Dev/labs/git-subtree-submod/submod

...but it is a bit of pain if the subtree has a lot of submodules. Is there a better way to do this?

like image 300
Edward Z. Yang Avatar asked Jul 31 '17 18:07

Edward Z. Yang


People also ask

How do you initialize a submodule?

If you already cloned the project and forgot --recurse-submodules , you can combine the git submodule init and git submodule update steps by running git submodule update --init . To also initialize, fetch and checkout any nested submodules, you can use the foolproof git submodule update --init --recursive .

How do I combine submodules?

In order to update an existing Git submodule, you need to execute the “git submodule update” with the “–remote” and the “–merge” option. Using the “–remote” command, you will be able to update your existing Git submodules without having to run “git pull” commands in each submodule of your project.

Can submodules have submodules?

Cloning a Project with Submodules If you pass --recurse-submodules to the git clone command, it will automatically initialize and update each submodule in the repository, including nested submodules if any of the submodules in the repository have submodules themselves.

How do I clone a repository with submodules?

The list of steps required to clone a Git repository with submodules is: Issue a git clone command on the parent repository. Issue a git submodule init command. Issue a git submodule update command.


1 Answers

From what I can tell reading the docs and source code... Git subtree is completely separate from Git submodules and will not actively manage any submodules that may be contained within the subtree project itself.

As you found out, .gitmodules, which is critical to the function of git submodule init, needs to be maintained in the root of the "main" repository (for lack of a better term).

Upon further consideration, it is clear what the problem is: the subtree mechanism has added subtree's submodule reference to submod to the tree, but the .gitmodules metadata remains in subtree/.gitmodules, not the top-level .gitmodules, which means that git submodule init fails. If we copy the contents of subtree/.gitmodules to .gitmodules, adjusting all the paths accordingly, that solves the problem...

I strongly recommend not mixing these features.

like image 115
Anthony Mastrean Avatar answered Sep 22 '22 23:09

Anthony Mastrean