ln (English: /lษหn/) is a
natural way to consume the
git log. This is an entirely opinionated wrapper for git log, and to some
extent it's really just a really convoluted shell alias for git log.
If you want something pretty darn close, feel free to simply
$ LN_FMT='%C(yellow)%h%C(auto)%d %Creset%s %C(241)(%C(246)%ar%C(241))%Creset'
$ git config set pretty.ln $LN_FMT
$ git log --graph --oneline --format=ln
ln spawns a total of 3 child processes.
- An
exec()call togit log. - A parser that reads the output of
git logand does simple string parsing to make the output pretty. - An
exec()call tolesswithSTDINpiped so it appears as though we did something likegit log | lessin a shell.
And for that we need two pipes.
โญโโโโโโโโโโฎ pipe #1 โญโโโโโโโโโโฎ pipe #2 โญโโโโโโโโโโฎ
โ git log โโโโโโโโโโโโโโโค printer โโโโโโโโโโโโโโโค less โ
โ (A) โ[1]โโโโโโโ[0]โค (B) โ[1]โโโโโโโ[0]โค (C) โ
โฐโโโโโโโโโโฏ โฐโโโโโโโโโโฏ โฐโโโโโโโโโโฏ
It is possible that the git log output is bigger than the (fixed) capacity of
the pipe #1. This is important because while debugging if you don't let (B)
read continuously from pipe #1, then there is a chance that (A) would block
on writing to that pipe. Likewise for pipe #2.
You might be wondering why must we fork one last time to run less. Why not
just call exec() on the parent process and hand control to less? That's pretty
much what it would look like with the shell command git log | less right?
Well, we fork a child process for less because it consumes STDIN lazily (it
doesn't flush/clear STDIN upon exit). So if we call exec("less", ...) on the
parent process and less exits early, then we might be back in the situation in
the previous paragraph where the (B) blocks on writing to pipe #2, causing
ln to survive as a zombie process.
ln does basically no CLI argument parsing. It looks out for one and only one
flag, --bound. This will tell ln to truncate the git log output to the
height of the terminal window, if such a terminal window exists. All other CLI
arguments are passed straight on to the exec() call to git log.
To install ln, simply run
$ make configure
$ make install
In particular, a binary called git-ln will be installed (to whichever prefix
you set in CMakeLists.txt). This allows you to run git ln (without the
hyphen), enabling commands like git -C <repo> ln --all.
There is a quick and simple valgrind command in the Makefile to evaluate
ln's memory profile. It does find one leak when ln is compiled with
glibc, but that's due to fdopen's leak ( (cf)
here and
here).
