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
/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
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