A somewhat unknown bit of git trivia is that git rebase is implemented as a ~600 line shell script. A few months ago, I did a full-distro upgrade on my machine. I kept working while it updated, and was surprised when git add --patch failed, because I was using other git commands just fine. Even weirder, plain git add worked! The message I got mentioned Perl and .pm files.

This made me a bit curious to find out what other bits of git were outside the git binary and not in C. Knowing that rebase was a shell script, and that the convention for external subcommands was git-$SUBCOMMAND, I could strace git to find out where that script lived:

$ strace -fe execve git rebase 2>&1 >/dev/null | grep git-rebase
[pid 21289] execve("/usr/lib/git-core/git-rebase", ["git-rebase"], [/* 51 vars */]) = 0

Ok, so /usr/lib/git-core is the place to look! How many executables in there?

$ find /usr/lib/git-core -type f -executable | wc -l
37

How many are shell scripts?

$ file /usr/lib/git-core/* | grep 'shell script' | wc -l
18

Let’s see which ones!

$ file /usr/lib/git-core/* \
> | grep 'shell script' \
> | cut -f1 -d: \
> | xargs basename -a \
> | column                                       
git-gui--askpass        git-filter-branch       git-submodule
git-citool              git-merge-one-file      git-stash
git-gui                 git-merge-resolve       git-rebase
git-difftool--helper    git-request-pull        git-bisect
git-mergetool           git-web--browse         git-quiltimport
git-merge-octopus       git-instaweb            git-subtree

Some of the surprising ones for me: git submodule, and git subtree because they seem ‘important’, as well as git-stash which seems like a ‘built-in’ facility. Of course, they are all important and built-in in that they come with git-core! I think this is mostly a reflection of my programming background: I’d never implement something complex in shell because I just can’t do it quickly enough for it to make any sense.

How about stats on the types of files?

$ find /usr/lib/git-core/ -type f -executable \
> | xargs file \
> | cut -d' ' -f 2- \
> | sed 's/^ *//;s/, interp.*//' \
> | sort \
> | uniq -c
     16 ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked
      3 Perl script text executable
     17 POSIX shell script, ASCII text executable
      1 POSIX shell script, ASCII text executable, with very long lines

We came here curious about git add --patch and Perl, and here we’ve got 3 Perl scripts. What are they?

$ file /usr/lib/git-core/* \
> | grep 'shell script' \
> | cut -f1 -d: \
> | xargs basename -a
git-difftool
git-relink
git-add--interactive

Aha! git-add--interactive sounds very likely. Of course we could have checked this much earlier on:

$ strace -fe execve git add -p 2>&1 >/dev/null | grep add
execve("/usr/bin/git", ["git", "add", "-p"], [/* 49 vars */]) = 0
[pid 22871] execve("/usr/lib/git-core/git", ["git", "add--interactive", "--patch", "--"], [/* 51 vars */]) = 0
[pid 22872] execve("/usr/lib/git-core/git-add--interactive", ["git-add--interactive", "--patch", "--"], [/* 51 vars */]) = 0

Proof. :-)