Monday, November 8, 2021

git log query, or: glq

Sometimes you've got to take the time to build something so you can be more productive. Also, it never hurts to make life easier on yourself. I've found git log can be a source of zen when combined with disciplined git commit messages.

To give you some background, I have a wrapper around the git command that templates commit messages. It helps to ensure consistent, detailed, quality commit messages for posterity. 

The template uses the following format:

KEYWORD: path/to/file/relative/to/repo/file.ext; Commit message here. (Ticket serial number, if applicable)

The KEYWORD can be one of: NEW, CHANGE, REMOVED, OOB. Some files are stored in a directory named after the host they're installed on, and the ticket serial number can vary depending on how the work request was received. 

Here is an example of a real commit message:

CHANGE: files/ssl-certificates/my.host.com/my.host.com.pfx; Updated SSL Certificate and rotated private key. (TKT002048)

This allows me to search the git log for things like "NEW" files, the last "CHANGE" made to an SSL Certificate or firewall config, or when files were "REMOVED". This also helps me provide an easily searchable git audit log, should I ever need to, during a Compliance Audit or Incident Investigation.

However, using git log --grep "CHANGE.*my.host.com.pfx" --extended-regexp -n 1 got to be a bit cumbersome. I wanted a short command that could also take an option to increment "-n" as needed. A script felt like overkill for this situation, so I opted for a BASH function that's loaded into the shell session via .bashrc (on most GNU/Linux) or .bash_profile (on macOS). 

With this function, I've created a simple command: glq

Here is an example of how glq can quickly return the latest commit where the firewall configuration was changed for the host my.host.com:

$ glq "CHANGE.*my.host.com/firewall.yml"

Since git commits are "first come, first serve", a commit authored in Oct 1 could be merged on Nov 1 and would thus be considered the latest commit (or change). So, when thinking about the commit log in terms of, "descending, chronological order," we must think of it as the reverse (starting from now), chronological order in which commits were added/merged into your working branch.

By default, glq will only return the latest, first matching commit. If you want to expand the limit to 5, you can specify an integer after the double-quote encapsulated search query. 

For example:

$ glq "CHANGE.*my.host.com/firewall.yml" 5

The above example (building off the previous example) has "5" specified after the search query. This (essentially) tells glq/git to limit matches to the five most recent commits, instead of only the latest one. 

For even more fun, if I want to find the latest commit where a customer requested a change to a system, I could use the following search query:

$ glq "CHANGE.*customer.host.com/firewall.yml.*TKT"

Which would match the following commit message:

CHANGE: host_vars/customer.host.com/firewall.yml; Customer requested opening port 8443. (TKT004096)

As you can see, this has the potential to be a very powerful tool. It really only works, though, if you are consistent with your commit message formatting either through policy or template, or both.

Have fun!