Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pushing all submodules recursively

I wrote the below script to push all the changes in the workspace, both in the submodules and the superproject. However, it sounds a little odd that, it is this complex to do what I want. Is there any better way, that I'm missing?

#!/bin/bash

if [ "$#" -ne 1 ]; then
    echo "Illegal number of parameters"
    exit
fi

SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

cd "${SCRIPT_DIR}/../submodule1" 
git status
git add -A
git commit -m "$1"
git push origin master

cd "${SCRIPT_DIR}/../submodule2" 
git status
git add -A
git commit -m "$1"
git push origin master

cd "${SCRIPT_DIR}/../submodule3" 
git status
git add -A
git commit -m "$1"
git push origin master

printf "\n\nUpdating Super Project\n\n" 
cd .. 
git status
git add -A
git commit -m "All Submodules Updated - $1"
git push origin master
like image 382
noway Avatar asked Jul 11 '14 09:07

noway


People also ask

How do I update submodules recursively?

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 pull all submodule?

Once you have set up the submodules you can update the repository with fetch/pull like you would normally do. To pull everything including the submodules, use the --recurse-submodules and the --remote parameter in the git pull command .

Can you push to a git submodule?

Pushing updates in the submodule. The submodule is just a separate repository. If you want to make changes to it, you should make the changes in its repository and push them like in a regular Git repository (just execute the git commands in the submodule's directory).

Do submodules update automatically?

Submodules are very static and only track specific commits. Submodules do not track git refs or branches and are not automatically updated when the host repository is updated. When adding a submodule to a repository a new . gitmodules file will be created.


1 Answers

The git-powercommit script I wrote recently does push submodules recursively as a part of its workflow. Under the hood, there is a map-like iterator which uses git-status --porcelain=v2 to iterate over repository objects. Here is its definition:

mapchanges() {(
  set -e -x
  local filter="$1"
  local commiter="$2"
  git status --no-renames --porcelain=v2 | \
  while read N XY sub mH mI mW hH hI path ; do
    $filter $N $XY $sub $mH $mI $mW $hH $hI "$path"
  done | \
  sort -u --reverse | \
  while read path; do
    $commiter "$path"
  done
)}

In order to iterate over submodules, you need to provide it with the filter and the action callback functions. In your case, the filter function could be:

filter_subm() {
  # Inputs are according to `git status --porcelain=v2` spec. The function
  # filters submodules which has changed commits.
  local sub="$3"; shift 8; local path="$1"
  case "$sub" in
    SC??) echo "$path" ;;
    *) ;;
  esac
}

As for the action function, the origina script does commit the whole submodule, but in your case you could insert the push commands like the following

push_subm() {
  local path="$1"
  (cd -P "$path" && git push origin; )
}

Now, we bring everything together with the line like

mapchanges filter_subm push_subm

Please, consider reviewing the original script to find out the details on how to organize the recursion.

like image 108
grwlf Avatar answered Oct 13 '22 04:10

grwlf