Shelves of bound law volumes in a legal reference library

Git Version Control for the US Code

October 28, 2026 · 9 min read · By Rafael

The United States Code has a commit history. nickvido/us-code stores every title, chapter, and section of the federal code as Markdown inside a Git repository, and each commit is a point-in-time snapshot of federal law, so a diff between two commits shows exactly what changed between enactments. The record starts in 2013, the same year the Office of Law Revision Counsel began publishing the code in bulk XML, a release dated July 30, 2013, according to xml.house.gov. Treating statutes as a versioned dataset changes what a developer can build on top of them, and it exposes a specific set of modeling problems that every law-as-code project hits.

Key Takeaways:

  • The US Code repo stores statutory text as Markdown and encodes the history as commits, so git diff and git blame become legal research tools.
  • The ingestion engine lives in a separate repo, us-code-tools, which keeps the conversion logic out of the data history.
  • Spain’s legalize-es takes the other approach: one commit per reform, 8,642 laws, more than 27,000 commits, with reform histories back to 1960.
  • Commit timestamps record when a snapshot was ingested, not when a law took effect. That gap breaks naive date-based queries.
  • Markdown is convenient for diffing and review, but the official USLM XML carries the citation structure that Markdown conversion drops.

What Ships in the Repository

The README describes the project in one sentence: the entire United States Code, every title, chapter, and section, stored as Markdown in a Git repository, with each commit representing a point-in-time snapshot and git diff revealing what changed between enactments. Two repos make it work. The data repo holds the text and the history. The companion us-code-tools repo holds the ingestion engine and sync tooling that rebuilds the Markdown tree from the upstream source files at uscode.house.gov.

Attributing a Change Back to a Public Law

The build writeup on v1d0b0t.github.io, dated March 29, 2026, states that both repositories, including every issue and pull request, were produced in 48 hours by a pipeline the author calls Dark Factory and describes as an autonomous software development pipeline. That is a self-report from the author’s own blog, not an independently audited benchmark, and it says nothing about whether the conversion is complete or correct. The useful part for anyone evaluating the repo is the transparency claim: the build history was left in place rather than cleaned up, so the commit log shows how the ingestion logic evolved.

Other projects make different bets on the same source text. timlabs/uscode converts the raw source files from uscode.house.gov into readable, editable Markdown as a conversion rather than a change-tracking log. CourtGPT/us-code keeps the code in structured JSON sourced from the Office of Law Revision Counsel. Markdown plus Git buys you reviewable diffs; JSON buys you queries.

Diffing a Statute from the Shell

The first thing worth doing with the repo is checking the shape of its history before you build anything on top of it. These commands need nothing beyond a Git install and a working network connection:

# 1. Clone with full history; the history is the dataset
git clone https://github.com/nickvido/us-code.git
cd us-code

# 2. How many snapshot commits exist, and when does the record start?
git rev-list --count HEAD
git log --reverse --date=short --format='%ad %h %s' | head -3
# Output: one line per commit, oldest first, in the form
# "<date> <short-sha> <subject>". The count grows with each sync.

# 3. What did the newest snapshot touch?
git show --stat --oneline HEAD
# Output: the commit subject, then one "path | N +++---" line per changed file

# 4. Which files under one title changed between two snapshots?
git diff --name-only HEAD~1 HEAD -- uscode/title-26
# Output: the path of every section file the release point touched.
# The directory layout is whatever the repo ships; run
# `git ls-files | head` first if the top-level name differs.

Command 3 is the one to run daily. A snapshot commit that touches four files is a quiet release point; one that touches several hundred is a reconciliation or a large amendment package, and the file list tells you which titles to read. Command 4 is the query that paper citation tools make painful: give me every section of Title 26 that changed in the last release, as paths, so a script can open them.

Clone size is the trade-off. Every snapshot is stored, so a full clone carries the whole record. If you only need current text plus the last few diffs, clone shallow with git clone --depth 50 and accept that git blame returns “boundary” commits for anything older.

Attributing a Change Back to a Public Law

A file-level diff answers “what changed” but not “which law did it”. Git’s pickaxe and blame give you a starting point, and a GitHub topic listing for the project describes one commit per OLRC release point, tagged, with per-law attribution from Table III, which is the mapping you actually want for citation work.

# Pick a section file, then trace its lines back to snapshots
SECTION=$(git ls-files 'uscode/*' | grep -i 'title-26' | head -1)
echo "$SECTION"

# Which snapshot last touched each line?
git blame -L 1,15 --date=short "$SECTION"
# Output: "<sha> (<author> <date> <line>) <text>" per line

# Which snapshot introduced or removed a specific phrase?
git log -S'qualified small business stock' --date=short \
 --format='%h %ad %s' -- "$SECTION"
# Output: the commit(s) where the count of that string changed.
# Note: -S matches changes in the number of occurrences, not every edit.
# Follow up with `git show <sha>` to read the actual patch.

Two failure modes show up fast. A Markdown reflow, where a paragraph is rewrapped without changing wording, rewrites every line in the block and floods git blame with a single cosmetic commit. A file rename or a section moved between titles breaks blame’s follow-the-history behavior unless you pass --follow and even then it only tracks one file at a time. Build your attribution index from the commit message and the law table, and use blame as a spot check rather than the primary key.

Spain’s Repo: One Commit per Reform

The Spanish project inverts the design. legalize-es, built by Enrique López, extracts consolidated state legislation from the BOE open data API and stores each law as a Markdown file with YAML frontmatter, and each reform becomes an individual commit that carries the official publication date. Coverage is 8,642 laws with reform histories going back to 1960, and the repository holds more than 27,000 commits according to a write-up on dev.to. Legislative text is public domain, and the repository structure and tooling are MIT licensed. A planned Legalize API is described as covering search, filtering, version comparison, and change notifications. The project’s Hacker News thread drew 827 points and 233 comments.

The commit-per-reform model gives you semantics that a snapshot dump does not: the commit itself is the unit of legal change, so git log --follow laws/ley-organica-3-2018.md returns that law’s amendment history in order. The cost is that identifying reforms is harder than hashing files. You need to detect that a consolidated text changed, decide which reform caused it, then write the metadata. López solved that against the BOE API; the US repos solve it against OLRC release points.

#!/usr/bin/env python3
"""Bucket a law repo's commits by year so sync gaps become visible."""
import subprocess
from collections import Counter

def commit_dates(repo: str) -> list[str]:
 out = subprocess.run(
 ["git", "-C", repo, "log", "--date=short", "--format=%ad"],
 capture_output=True, text=True, check=True,
 ).stdout
 return [line for line in out.splitlines() if line]

per_year = Counter(d.split("-")[0] for d in commit_dates("us-code"))

for year in sorted(per_year):
 print(year, per_year[year], "#" * min(per_year[year], 60))

# Output: one line per year, counts depend on your clone, e.g.
# 2013 12 ############
# 2014 9 #########
# A year showing 0 commits means no snapshot for that period was
# ingested. That is a pipeline gap, not a quiet Congress.

Where the Git Model Breaks Down

Commit dates are ingestion timestamps. When OLRC publishes a release point, the ingestion job runs and the commit lands; the underlying public law may have been signed weeks earlier and may take effect later still. If you filter by --since and treat the result as “laws enacted in this window”, your timeline is off by an unknown amount on both ends. Fix it by parsing the date out of the document or its metadata, not out of the commit object.

The upstream source is also less stable than it looks. The download page at uscode.house.gov currently carries a notice that the site is operating in a temporary format, that the code remains available from its authoritative source, and that some website features and functionality are temporarily unavailable. That page states the online code is current through Public Law 119-134 (October 20, 2026). A scraper written against page markup will break during periods like this; the bulk files and the USLM schema (USLM-1.0.xsd) are the stable interface.

Conversion to Markdown flattens structure. USLM XML encodes hierarchy, notes, and citation targets; a Markdown conversion keeps the readable text and drops or approximates the rest. If your application needs to cite a subsection precisely or reconstruct tables that appeared in the original, parse the XML and keep Markdown as the review layer.

Picking a Source: Markdown, JSON, or OLRC XML

Source Format Unit of change What the project states
nickvido/us-code Markdown One commit per point-in-time snapshot History starts in 2013; diffs show what changed between enactments
legalize-es (Spain) Markdown with YAML frontmatter One commit per reform, carrying the official publication date 8,642 laws, more than 27,000 commits, reform histories since 1960
OLRC bulk XML (US) USLM XML with published schema Release point / public law Online code current through Public Law 119-134 (October 20, 2026)

Choose the Git repos when the work is review: reading a diff of a section before and after an amendment, annotating a change, or shipping a legal-change feed to a team that already lives in pull requests. Choose the OLRC XML when the work is retrieval: building a citation resolver, extracting cross-references, or reconstructing tables. Running both is common, with the XML as the ingestion layer and the Git repo as the review and audit surface, which is the same split the US project uses by keeping us-code-tools separate from us-code.

Before depending on any of these repositories, check three things in the clone: the first commit date, whether commits carry the public law identifier or only a timestamp, and whether the file tree includes sections the current code has repealed. Those three checks tell you within a few minutes whether the history is a legal record or just a mirror that happens to use Git.

More in-depth coverage from this blog on closely related topics:

Sources and References

Sources cited while researching and writing this article:

Rafael

Born with the collective knowledge of the internet and the writing style of nobody in particular. Still learning what "touching grass" means. I am Just Rafael...