Ben Lobaugh Online

I think, therefore I am. I am, therefore I sail

Category: Git Page 1 of 2

Bash script to automatically convert git submodules to regular files

Git submodules drive me batty! They are a great idea in theory however in practical application they are a pain in the butt to work with.

I have a project that has accumulated over a dozen submodules over the past couple years. Switching branches and merging anything has become excruciating. This morning was the last straw. I WANT THEM GONE! Removing dozens of submodules by hand is time consuming so I tossed together this quick Bash script. I hope it is helpful to anyone else out there struggling with git submodules.

#!/bin/bash

# Get a list of all the submodules
submodules=($(git config --file .gitmodules --get-regexp path | awk '{ print $2 }'))

# Loop over submodules and convert to regular files
for submodule in "${submodules[@]}"
do  
   echo "Removing $submodule"
   git rm --cached $submodule # Delete references to submodule HEAD
   rm -rf $submodule/.git* # Remove submodule .git references to prevent confusion from main repo
   git add $submodule # Add the left over files from the submodule to the main repo
   git commit -m "Converting submodule $submodule to regular files" # Commit the new regular files!
done

# Finally remove the submodule mapping
git rm .gitmodules

Reset all git submodules

Here is a quick snippet that will reset all your git submodules to their most recent commit. Handy when something has happened such as a file permissions change that unintentionally affected the submodules.

git submodule foreach --recursive git reset --hard

Compare a single file between git branches

Comparing a file between two git branches is quite easy. You can do it with both diff and difftool.

Straight diff

git diff BRANCH_ONE BRANCH_TWO -- FILE

Using difftool

git difftool BRANCH_ONE BRANCH_TWO -- FILE

Make an empty git commit

Occassionally I have need to mark a specific moment in a git repository. Often this mark is to call out a deployment point. If everything has already been committed I will use an “empty commit” as a marker. Git makes this quite easy and in fact it is built into the commit command.

Run the following and your commit editor of choice will open to provide the commit message:

git commit --allow-empty

Alternatively you can provide the commit message inline with the standard -m

git commit --allow-empty -m "New commit message"

Autocomplete git branches and commands in bash

The tab completion for commands in bash is awesome, but it does not work for bash out of the box. Lucky for us it is relatively easy to get bash completion working.

You will need two things, a copy of the completion script and an update to your bash profile.

The completion script is available at: https://github.com/git/git/blob/master/contrib/completion/git-completion.bash

Then in your .bashrc (or .bash_profile, or .profile, whatever you are setup for) add the following:

if [ -f ~/.bin/git-completion.bash ]; then
  . ~/.bin/git-completion.bash
fi

Be sure the path to the git-completion.bash file is correct for your system. On mine I keep extra commands in ~/.bin.

Start using your new completion with:

source ~/.bashrc

Now simply type ‘git’ and hit tab to see all the commands available.

When switching branches type ‘git checkout’ and hit tab to see a list of the branches.

Page 1 of 2