mazlix
mazlix

Reputation: 6313

Automatically Add All Submodules to a Repo

I have a big Directory ~/.vim and in it I have a subdirectory with many other git repos in it. I want to make a git repo of my ~/.vim directory though, but don't want to go through each of my other git subdirectories.

Is there any way of just recursively going through and adding all submodules?

Upvotes: 9

Views: 5286

Answers (7)

Ankit Kumar
Ankit Kumar

Reputation: 496

I would recommend to create a python script

import 
glob,remodules = glob.glob('*/**/.git', recursive=True)
content = ''def get_url(submod):
    for line in open(submod+'/config','r'):
       if '\turl' in line:
           return line.split('=')[1].strip()
for submod in modules:
    content += f'''
[submodule "{submod.strip(".git/")}"]
    path = {submod.strip(".git/")}
    url = {get_url(submod)}
    '''
print(content)
with open('.gitmodules','w') as f:
    f.write(content)

and push the changes into your github using the following command

git add . 
git commit -m "Adding submodule"
git push origin branch_name 

There might be chances that some of the files will be not added , you can simply add the generated .gitmodules file and add them manually. In case you are seeing that some of the files are giving error either edit the above code according to the location or you can delete them temporarily and add them manually to get best out of it.

example of .gitmodules

[submodule "src/abc"]
    path = src/abc
    url = https://github.com/abc.git

Upvotes: 0

Ankit Kumar
Ankit Kumar

Reputation: 496

@Mussa When I am doing it it's showing me

The following path is ignored by one of your .gitignore files:

Use -f if you really want to add it.

Upvotes: 0

Mussa Charles
Mussa Charles

Reputation: 4432

Since doing this can be a repetitive task in many projects, I have created two helper functions based on awesome @Fatih answers with few modifications and store them in my machine using a custom bash shell file.

These functions can be invoked in any folder without the need of remembering or typing all of the implementation details.

Here are the steps to make life easier:

In your user root path create a file something like

.myBashCommands.sh

Write the following contents in it, If you already have your own dedicated file for custom functions, feel free to use it instead.

#!/bin/bash

# Find and log all git sub-modules if exist without making any changes.
# Credits: https://stackoverflow.com/a/10607225/7551807
function logAllGitSubModulesIfExist() {
 for x in $(find . -type d) ; do
 if [ -d "${x}/.git" ] ; then
     cd "${x}" ;
     origin="$(git config --get remote.origin.url)" ;
     cd - 1>/dev/null;
     echo "found gitsubmodule at =>" "${origin}" "${x}" "\n";
 fi ;
 done
}

# This loop first finds directories only, looks for a .git directory, identifies the original URL and then adds the submodule.
# Credits: https://stackoverflow.com/a/10607225/7551807
function addAllGitSubModules() {
for x in $(find . -type d) ; do
    if [ -d "${x}/.git" ] ; then
        cd "${x}"
        origin="$(git config --get remote.origin.url)"
        cd - 1>/dev/null
        git submodule add "${origin}" "${x}"
    fi
done
}

Close the file and while you are still in the same working directory, Refresh your terminal so that it recognize your newly added methods.

Here is how to do it: -

source .myBashCommands.sh

That's it! Now you are ready to reuse the two functions in any project and in any folder.

To invoke the methods simply type the name.

For example to log all available submodules just type the following in your terminal

logAllGitSubModulesIfExist

Similarly to find and add all existing submodules, just type the following: -

addAllGitSubModules

Upvotes: 0

Alexander Mills
Alexander Mills

Reputation: 100210

sadly, this feature doesn't seem to exist. git should have a command that can add all the modules referenced in .gitmodules, something like:

### wishful thinking

git submodules init --all
git submodules add --all

:(

Upvotes: 0

Fatih Arslan
Fatih Arslan

Reputation: 17127

Suppose that .vim is already a valid git repo and your want to add all git repos to your main git repo, then the for loop below is probably what you need:

First, cd to the root of your git repository.

Paste-able preview command- echo only, won't make any changes:

for x in $(find . -type d) ; do if [ -d "${x}/.git" ] ; then cd "${x}" ; origin="$(git config --get remote.origin.url)" ; cd - 1>/dev/null; echo git submodule add "${origin}" "${x}" ; fi ; done

Paste-able command to add the submodules:

for x in $(find . -type d) ; do if [ -d "${x}/.git" ] ; then cd "${x}" ; origin="$(git config --get remote.origin.url)" ; cd - 1>/dev/null; git submodule add "${origin}" "${x}" ; fi ; done

This loop first finds directories only, looks for a .git directory, identifies the original URL and then adds the submodule.

Readable version:

for x in $(find . -type d) ; do
    if [ -d "${x}/.git" ] ; then
        cd "${x}"
        origin="$(git config --get remote.origin.url)"
        cd - 1>/dev/null
        git submodule add "${origin}" "${x}"
    fi
done

Upvotes: 19

lumbric
lumbric

Reputation: 9093

cd /to/super/repo
root_path=$(pwd)
for submodule in $(find -mindepth 2 -type d -name .git); do
    submodule_dir=$root_path/$submodule/..
    remote_name=$(cd $submodule_dir && git rev-parse --abbrev-ref --symbolic-full-name @{u}|cut -d'/' -f1 )
    remote_uri=$(cd $submodule_dir && git remote get-url $remote_name)

    echo "Adding $submodule with remote $remote_name..."

    # If already added to index, but not to .gitmodules...
    git rm --cached $submodule_dir &> /dev/null

    git submodule add $remote_uri $submodule_dir
done

Upvotes: 1

shellcat_zero
shellcat_zero

Reputation: 1147

I had git repos nested in deeper sub-directories, so to find and add them from any level of depth, I had to use: for i in $(find ~/Sources/* -type d -name .git) do cd $i && cd .. && git submodule add $(pwd) done

Upvotes: 0

Related Questions