Thursday, April 19

a git log with both tags and dates

Trying to write a human-readable changelog for wrt, I wanted to see git history that included:

  • commit hash
  • a datestamp
  • any tags pointing at a commit
  • subject line

Since tags are used to designate released versions, this should at least give me a rough idea of what changed between releases.

This was not as obvious as I wanted it to be. You can see the tags in gitk’s view of history, but I didn’t know how to extract it from git log. The usual searching led to:

$ git log --oneline --decorate
99a584f (HEAD -> master, tag: v5.0.0-alpha, origin/master, origin/HEAD) set version string to v5.0.0
e919a56 some comment tweaking; latest readme
7b543b5 address a bunch of hotspots from Devel::NYTProf, removing MethodSpit
3fa80ca link_bar(): retain actual <a> tag for current page in linkbar
cf3dd64 remove failing recent_month test
b5fe642 kill an extraneous space char in Markup.pm
c1e17a9 sync README.pod with latest from WRT.pm
7d80dd5 kill recent_month(), month_before(), and feed_print_latest()
143613f get_date_entries_by_depth()
4f9a71b (tag: v4.3.0) switch example config from p1k3.com to example.com urls

Which is pretty close - you can see the tags inline with the rest of the history, but no date. (I’m not sure if I ever knew about --decorate; almost feels like it should be the default.)

I spent some time with git help log and eventually landed on:

$ git log --date=short --pretty='format:%h %ad %d %s'
99a584f 2018-04-19  (HEAD -> master, tag: v5.0.0-alpha, origin/master, origin/HEAD) set version string to v5.0.0
e919a56 2018-04-19  some comment tweaking; latest readme
7b543b5 2018-04-11  address a bunch of hotspots from Devel::NYTProf, removing MethodSpit
3fa80ca 2018-04-08  link_bar(): retain actual <a> tag for current page in linkbar
cf3dd64 2018-04-08  remove failing recent_month test
b5fe642 2018-04-08  kill an extraneous space char in Markup.pm
c1e17a9 2018-04-08  sync README.pod with latest from WRT.pm
7d80dd5 2018-04-08  kill recent_month(), month_before(), and feed_print_latest()
143613f 2018-04-08  get_date_entries_by_depth()
4f9a71b 2018-04-06  (tag: v4.3.0) switch example config from p1k3.com to example.com urls
a5e5f21 2018-04-06  render feed for last n day entries instead of for current month
77d90d2 2018-02-10  (tag: v4.2.2) fix --config option to wrt-display & wrt-render-all

This is better. In the format:

  • %h is hash
  • %ad is author date (shorted by the --date=short option)
  • %d is any ref pointing at that commit, which will include tags (it’s %d by analogy to the --decorate option)
  • %s is subject

Not super obvious, but it could be worse.

The other thing this did for me is re-cement the notion of what references are. If you look in a repo’s .git/refs/ directory, you’ll see something laid out roughly like the following:

$ tree .git/refs
.git/refs
├── heads
│   ├── jsonfeed
│   ├── master
│   └── subcommands
├── remotes
│   ├── origin
│   │   ├── HEAD
│   │   ├── master
│   │   └── subcommands
│   └── p1k3_server
│       ├── master
│       ├── tag_list
│       └── topiclinks
└── tags
    ├── v4.2.0
    ├── v4.2.2
    ├── v4.3.0
    └── v5.0.0-alpha

If you look at the contents of any of these files, you’ll see that they just contain some hashes which point to objects.

$ cat .git/refs/heads/master
99a584fb080e1f295d9522b684ab05f80f60918e

$ cat .git/refs/remotes/origin/master
99a584fb080e1f295d9522b684ab05f80f60918e

$ cat .git/refs/tags/v4.3.0
0ad7dbe5249aff2eab05e8c7f6d8d73c41fc7323

Because git actually has two kinds of tags, you might have some tags that don’t show up in that directory tree. Lightweight tags are, apparently, just commit objects. I’m not totally sure how this works, but you can get a better idea of it with:

$ git tag -l --format="%(objectname:short) %(refname)%09%(objecttype)"
2c789d3 refs/tags/2007-03-10    commit
a1f5c23 refs/tags/2007-06-20    commit
88a445e refs/tags/2007-06-21    commit
17beaef refs/tags/2007-07-07    commit
dac8154 refs/tags/2007-08-08    commit
221d1a3 refs/tags/2007-09-11    commit
54016b2 refs/tags/2007-10-04    commit
5437005 refs/tags/2008-01-11    commit
3c76277 refs/tags/2008-01-28    commit
20551c0 refs/tags/2008-03-15    commit
4bd68fe refs/tags/v4.2.0        tag
84948fa refs/tags/v4.2.2        tag
0ad7dbe refs/tags/v4.3.0        tag
199f704 refs/tags/v5.0.0-alpha  tag

The ones with an object type of “commit” are lightweight tags, the others are annotated.

Useful docs:

I should probably invest more time in understanding the contents of a .git.