How to add existing sub repository as a submodule in git?
I have a private codespace
supermodule with submodule
You don't need to clone manually first. After running git submodule add [url] [path]
run git submodule update
, which will clone/pull all submodules for you.
Where you went wrong is doing the
$ git add .
That adds everything, so also foo/bar
, to the index of the current repository (ready to be committed thus).
If you just don't do that and continue with
$ git submodule add https://github.com/CarloWood/XYZ.git foo/bar
then that should work; this would detect that foo/bar is an already cloned repository and add it to the current repository as a submodule.
Note that it is not needed to clone first. You explicitly say you already have done that, but for clarity for other readers I'd like to point out that if you omit the clone right before the git add .
too (so there isn't a foo/bar at all now) then the above git submodule add ...
would see there isn't anything yet and then simply clone it for you.
Note that there is a minor difference between methods. If you start with cloning then foo/.git
will be a directory, while if you use git submodule add
to do the cloning then this .git
repository is put in .git/modules/foo
of the parent project and foo/.git
is a file containing the path to that. There is no real difference however as using a file for the .git
to point anywhere else is generic and could be used anywhere; you can not conclude anything from .git
being a file or directory.
git submodule add
detects if the path given for a submosule exists and contains an initialized git repo, so no neeed to worry about that. I ran into a similar problem so I wrote a (hacky) script to deal with this issue.
#!/bin/bash
# save super directory
currentDir=`pwd`
# get all the git repos inside (except .) and format them
# the way git does
gitDirs=`find -type d -name ".git" | sed -e 's|.git$||' -e 's|./||' -e 's|/$||' | grep -v "^$"`
for i in ${gitDirs[@]}
do
echo "dealing with $i now"
cd $i
# get the remote url for each submodule
fetchUrl=`git remote -v | awk '/fetch/ {print $2}'`
# for my purposes repos without remotes are useless
# but you may have a different use case
if [[ -z $fetchUrl ]]
then
echo "fetch url not found for this directory"
continue
else
echo "got a fetch url of $fetchUrl for git repo $i"
fi
cd $currentDir
# make sure it isn't tracked as a submodule already
existing=`grep -A5 $i ./.gitmodules | grep $fetchUrl`
if [[ -z $existing ]]
then
echo "does not exist in .gitmodules yet, will create now"
# if it doesn't exist yet then create it
git submodule add $fetchUrl $i
else
echo "$i is already present as a submodule with fetch url: $fetchUrl"
echo "The command we would have used is: git submodule add $fetchUrl $i"
fi
done
One way to do it is to manually create the .gitmodules
file.
The format is below:
[submodule "path/to/submodule1"]
path = path/to/submodule/1
url = git@github.com:user/submodule1
[submodule "path/to/submodule2"]
path = path/to/submodule/2
url = git@github.com:user/submodule2
Note you'll have to run
git submodule sync
to apply the changes
foo/bar
: git rm -f --cached foo/bar
git submodule add https://github.com/octocat/Spoon-Knife.git ./foo/bar