If this content overflows, use the left and right arrow keys to scroll horizontally.

Version numbers your git history already knows.

GitCalVer turns your default branch’s history into unique, increasing versions. Nothing to bump, no state to keep.

20261017
.
1
UTC date 20261017 The commit’s committer date, in UTC.
Commit count 1 Commits reachable from this one, through any parent, that share its UTC day.

The first commit on 2026-10-17 (UTC) is 20261017.1.

How it works

GitCalVer is a deterministic function of history. Give it a commit, get its version. Give it a clean version, get the commit back.

1

Take the commit’s UTC date

Committer date, normalized to UTC, formatted as YYYYMMDD. Time zones never leak in.

2

Count commits on that date

Count every commit reachable from this one—through any parent—that shares its UTC date. A same-day merge can add more than one at once.

3

Join them with a dot

The result is YYYYMMDD.N—e.g. the third commit on April 11 is 20260411.3.


Boring on purpose

Strictly increasing

Later commits always sort after earlier ones—compare the date, then N as an integer: 20260607.2 < 20260607.10 < 20260608.1. This holds as long as committer dates never go backwards.

Unique per commit

Each commit in the default branch’s first-parent history maps to one date-plus-count pair. Clean versions don’t repeat within that history.

Reversible

Pass a clean version back to GitCalVer and it returns the exact commit hash from that history. Versions are an index into your branch.

Zero config

No version file to bump, no tags to maintain by hand. The only dependency is git itself.


Everything that defines a version

format
YYYYMMDD.N
YYYYMMDD
The commit’s committer date in UTC, zero-padded. Local time is never used.
N
Count of commits reachable from this one, through any parent, sharing that UTC date—including this commit.
ordering
Compare as date, then as integer N. Strictly increasing as long as committer dates never decrease.
prefix
An optional literal string, e.g. 0. → 0.20260607.1 for SemVer tooling.
dirty
With optional --dirty, an uncommitted tree emits a marked, non-reversible version like 20260607.1-dirty.abc1234. By default, an uncommitted tree is rejected.
Read the full specification →

One file, one command

The reference implementation is a portable POSIX shell script. Its only dependency is git 2.15+.

install.sh
# grab the script, make it executable
curl -fsSLO https://github.com/gitcalver/sh/\
releases/download/v20261004.2/gitcalver.sh
chmod +x gitcalver.sh
run it
# version for HEAD
$ ./gitcalver.sh
20261017.1

# reverse: clean version → commit
$ ./gitcalver.sh 20261017.1
a1b2c3d4e5f6…
.github/workflows/release.yml
# compute a version on every push
- uses: gitcalver/sh@v20261004.2
  id: version
  with:
    prefix: '0.'