Skip to content

Repository files navigation

Alibi

What your commit history says about you.

    [TELLS  ] 1 address of yours, and not a forwarding address
             s*************1@gmail.com
               8 commits, 2019-04-01 to 2019-04-08

    [TELLS  ] Identities of yours that share a timezone
             all of these commit from UTC+2:
               s*m <s*m@users.noreply.github.com>
               S***********a <s*************1@gmail.com>

    [TELLS  ] Days your clock was somewhere else
             UTC-4     2024-08-14  2024-08-16

    [NARROWS] The hours you commit at
             18:00   ##########################     60
             20:00   ##########################     60
             21:00   ##########################     60
             22:00   ############################## 68
             23:00 .

             You have never committed between 23:00 and 11:00. A gap that
             long across 250 commits is not chance, it is a sleep schedule.

Every commit you have ever pushed carries your name, your address, and the timezone the clock was set to on the machine that wrote it. A few hundred of them draw the hours you are awake and the part of the world you are in.

Alibi reads that back to you.

The one nobody else checks

Git does not store the time in UTC. It stores the local time and the offset, on every single commit, forever. 2024-08-14T15:20:00-04:00 is not a timestamp, it is a statement about where you were sitting that afternoon.

Plenty of tools will draw you a chart of your commit hours. They present it as a fun fact about how much of a night owl you are. It is also:

  • the timezone you live in, on every commit, unhidden by anything;
  • the dates you were somewhere else, if you ever committed from a trip;
  • the hours you sleep, which barely move for most people over years;
  • and taken together, enough to match two accounts you thought were separate.

That last one is the point of the tool. If you keep a work identity and a personal one apart, or a real name and a handle, the addresses are the part you remember to change. The timezone and the sleep schedule are the part you cannot change, and they are in both.

What it finds

Addresses Every address you have committed under, including the ones you stopped using years ago, with the dates they were in use
Names Every name, and whether it reads as a full legal name rather than a handle
Correlation Identities of yours that share a timezone, which is how separate accounts get tied together
Timezones Where your clock was set, told apart from daylight saving, with the dates of anything that was not home
Hours The histogram, and whether the quiet stretch in it is really a sleep schedule or just a small sample
Days Whether this looks like a job or something you do around one
Messages Home directory paths, addresses typed into a body, and the people you have named in trailers

It works out which of the people in the history are you, so on a repository with a hundred contributors you get a report about yourself rather than a dump of the mailing list. Pass --me if it guesses wrong.

It only reads

  • It never writes. Not to the repository, not anywhere. A test reads the source and fails the build if a call that writes a file appears in it.
  • It never opens a socket. There is no network code in it, and the same test fails if any appears.
  • It runs git, and only git. Reading .git by hand would have been a few hundred lines of packfile handling to avoid depending on something already installed. So it shells out, from one file, through a list of five exact invocations, none of which can change a repository. git config --get user.email is on the list; git config is not.
  • It masks what it finds. Enough of an address to recognise which of your own it is, not enough to scrape out of a report you pasted somewhere. Use --reveal when you want the whole thing.

Running it

alibi
alibi ~/code/thing ~/code/other
alibi --me you@example.com --reveal

Exit code is 1 when the history names you, places you, or links two of your identities, 2 when it could not be read, 0 when there is nothing to say. That makes it usable from a script.

A gap is not a pass

A shallow clone has had its oldest commits cut off, and those are the ones most likely to carry an address you have since stopped using. A repository with nine commits in it cannot tell you anything about your working hours.

Alibi says so, in its own section, at the top, before any of the findings. A short report is not a clean history, and a tool that quietly gives up is worse than no tool: it hands you confidence you have not earned.

The same rule runs through the checks. Twenty empty hours out of six commits is not a sleep schedule, it is six commits, so the report does not claim one until the gap is bigger than chance would explain.

What you can actually do about it

Less than you would like, and the report says so rather than pretending otherwise.

Going forward is easy. Set a forwarding address, set a name you are happy to publish, and do it on every machine you commit from, which is the part people forget.

Going back is not. Rewriting history changes the hash of every commit after the one you touched, which breaks every fork, every open pull request, and every link anybody has ever posted to a line of your code. Anyone who already cloned it still has the old commits. For a repository nobody else has touched it is worth doing. For anything else, know what it costs first.

The timezone is worse: there is no setting for it. Git reads the clock. The only way not to publish it is to commit from a machine set to UTC, and that is its own tell, because almost nobody does.

Building

Needs Go and nothing else. No dependencies at all.

go build -o alibi .
go test ./...

The tests build real repositories with real git and read them back, so what is under test is what git writes rather than my idea of it.

What it does not do

It reports; it does not rewrite. git filter-repo exists and is better at that than anything I would write, and the decision to run it should be a decision, not a flag on an audit tool.

It reads commits. Tags, notes and the reflog carry names and dates too, and they are not in here yet.

Licence

MIT. Do what you like with it.

About

What your commit history publishes about you: forgotten addresses, your timezone, the hours you sleep, and the identities it ties together.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages