Personal Agency With Git Time Logging

Tracking time worked is unsexy at best, intrusive micro-management at worst. But I think understanding where time is spent lets individuals drive velocity through better choices. We can do this automatically with git hooks.

Terminal


$ git tag -n | grep time_
time_23ccc3b_fix_githooks          0d:0h:5m    secs=301
time_4aeeb7a_refactor_filestore    0d:22h:26m  secs=80685
time_8f0da2d_webui_blog_template   0d:19h:15m  secs=69313
time_c78833f_webui_try_now         2d:4h:12m   secs=18792

Each merged feature branch gets an automated time-tracking tag.

Knowing how much time is spent changing code in component x, lets us reason about entropy in the system. Showing your team mates that your swanky new AI co-worker enables you to be faster, could help you improve overall team productivity. Maybe you want to see if you're more effective when using Vim or VSCode, how else could you know than measuring over time?

Time-tracking as a fuzzy element of over-zealous Agile management turns many of us off. But when time-tracking is a tool developers can use for their own benefit, I’m all in for that.

Measure Beats Estimate

Good software development is not about making perfect software. It is about making software that’s good enough for the purpose, for maintainabilty, while not increasing entropy. Neglecting those last two is leaving free development cadence on the table.

It's taken a lot of trial and error to find a measure that feels a genuine reflection of time spent 'writing code'. While at the same time wrapped in a process that doesn't add any overhead.

My measurement spans from creating a new branch to merging that branch. A git hook automatically writes a log of the time taken to an annotated tag. That time is, objectively, how long I spent on implementation.

Now, bear in mind that this is still a vague measure of development time. But it's definitely less vague than guessing before starting the work. It’s meant to highlight the effort of making a change, excluding engineering/thinking time. All things being relatively equal, over a longer period, anomilies pop out.

Anomolies and trends in the data are things we can talk about in practical terms. Such as, “since we started using AI, average branch time is 10% less.” Or, “component X is getting progressively slower to maintain.”

Terminal


$ git for-each-ref 'refs/tags/time*' --format="%(*committerdate:short) %(refname:short) %(contents:subject)" | sort
2025-03-24 time_23ccc3b_fix_githooks         0d:0h:5m   secs=301
2025-03-23 time_4aeeb7a_refactor_filestore   0d:22h:26m secs=80685
2025-03-13 time_c78833f_webui_try_now        2d:4h:12m  secs=187925
2025-03-06 time_8f0da2d_webui_blog_template  0d:19h:15m secs=69313

Get tags with date.

It is not perfect, but it is good enough. I have far more realistic knowledge of how long I spend writing code, and where the slop is accumulating. My hope is that this will show the longer term effects of AI-assisted coding as an objective measure.

How It Works

I’ve put the hooks in a public repo, so I can pull them in all my projects via a Makefile. If you copy/paste this then redo the spaces as tabs in the for loop.

Terminal


$ cat Makefile
GIT_TIME_HOOKS= \
        https://raw.githubusercontent.com/thisdougb/git-time-hooks/main/commit-msg \
        https://raw.githubusercontent.com/thisdougb/git-time-hooks/main/pre-push

.PHONY: githooks
githooks:
        @cd .git/hooks && \
        for i in $(GIT_TIME_HOOKS); do \
                echo "installing git hook $$i"; \
                curl -sO $$i; \
                chmod +x "`echo $$i | rev | cut -f1 -d'/' | rev`"; \
        done

$ make githooks
installing git hook https://raw.githubusercontent.com/thisdougb/git-time-hooks/main/commit-msg
installing git hook https://raw.githubusercontent.com/thisdougb/git-time-hooks/main/pre-push

Makefile snippet to install git hooks for time tracking.

My feature development workflow begins by creating a new branch. Then I'll spend time making the change, and commit.

Terminal


$ git checkout -b fix_githooks
Switched to a new branch 'fix_githooks'

/* some work happens here */

$ git commit -m 'Fixes typo in githook scripts'
[fix_githooks 4b7912b] Fixes typo in githook scripts
 2 files changed, 2 insertions(+), 2 deletions(-)

When I’m done I switch back to master, and merge the changes.

Terminal


$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.

$ git pull
Already up to date.

$ git merge --squash fix_githooks
Updating 4aeeb7a..4b7912b
Fast-forward
Squash commit -- not updating HEAD
 .githooks/commit-msg | 2 +-
 .githooks/pre-push   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

Now I commit the merged changes, with the auto-generated commit message which contains the branch creation times. The push git hook will read this commit message and figure out the oldest time from all the time_branch_created lines.

Terminal


$ git commit
[master 23ccc3b] Squashed commit of the following:
 2 files changed, 2 insertions(+), 2 deletions(-)

$ git log -1
commit 23ccc3b8f980b038536910f96ac2ddaa8e47eae4 (HEAD -> master)
Author: Doug Bridgens 
Date:   Mon Mar 24 09:13:54 2025 +0000

    Squashed commit of the following:

    commit 4b7912b8249b9b8c4ec134a74749a31b8b30cadb
    Author: Doug Bridgens 
    Date:   Mon Mar 24 09:12:05 2025 +0000

        Fixes typo in githook scripts

        time_branch_created fix_githooks 1742807430

Finally, when I push the merge commit the pre-push hook fires and creates the time tag. The new tag is automatically pushed by the hook, with it's referenced commit following immediately afterwards.

Terminal


$ git push origin master
[pre-push] detected squash commit: 23ccc3b HEAD@{0}: commit: Squashed commit of the following:
[pre-push] detected branch: fix_githooks
[pre-push] tag added: time_23ccc3b_fix_githooks 0d:0h:5m secs=301
[pre-push] tag pushed: time_23ccc3b_fix_githooks 0d:0h:5m secs=301

Writing objects: 100% (5/5), 1.22 KiB | 1.22 MiB/s, done.
To git.far-oeuf.com:doocot-server
   4aeeb7a..23ccc3b  master -> master

$ git tag -n
time_23ccc3b_fix_githooks 0d:0h:5m secs=301

posted by Doug Bridgens, on 28 Mar 2025