Skip to main content

git-spreader

Test PyPI Python

A tool to make 3am commit binges look like responsible adult behavior — because the lie the contribution graph tells should at least be a plausible one.

Takes compressed bursts of commits (weekend hackathons, late-night sessions) and respaces them across realistic working hours — with jitter, flow-state clustering, occasional late-night/weekend commits, and random days off.

Installation

pip install git-spreader
# or
uv pip install git-spreader

Usage

Preview a schedule (dry run)

git-spreader preview HEAD~10..HEAD --start 2025-01-01 --seed 42
  #  Original Date          New Date                Score  Gap      Summary
  1  2025-02-15 02:14:33    2025-01-02 09:23:41     0.12   —        fix: typo in README
  2  2025-02-15 02:31:07    2025-01-02 09:48:15     0.08   25m      chore: update deps
  3  2025-02-15 03:45:22    2025-01-06 10:12:33     0.73   1d 25m   feat: add auth module
  4  2025-02-15 04:02:19    2025-01-06 14:45:08     0.45   4h 33m   feat: auth tests
  5  2025-02-15 04:15:41    2025-01-07 09:37:22     0.91   18h 52m  refactor: database layer

Rewrite timestamps

git-spreader spread HEAD~10..HEAD --start 2025-01-01 --seed 42

Set a fixed date range

git-spreader spread HEAD~20..HEAD --start 2025-01-01 --end 2025-01-31

Override working hours and days

git-spreader spread HEAD~10..HEAD --start 2025-02-01 --working-hours 08:00-16:00
git-spreader spread HEAD~10..HEAD --start 2025-02-01 --working-days Mon,Wed,Fri,Sat,Sun

Profiles

Built-in presets for common scheduling patterns:

Profile Hours Days Description
default 09:00–17:00 Mon–Fri Standard office hours
night-owl 22:00–04:00 Mon–Sun Late-night hacker
side-project 18:00–23:00 Mon–Sun Evenings after work/school
weekend-warrior 09:00–18:00 Sat–Sun Weekends only
git-spreader spread HEAD~10..HEAD --start 2025-02-01 --profile side-project

Explicit CLI flags override profile values:

# Use side-project profile but change hours to 20:00-23:00
git-spreader spread HEAD~10..HEAD --start 2025-02-01 --profile side-project --working-hours 20:00-23:00

Manage configuration

git-spreader init             # interactive first-run setup
git-spreader config --show    # print effective config
git-spreader config --edit    # open the global config in $EDITOR
git-spreader config --reset   # reset to defaults

How It Works

Complexity scoring

Each commit is scored by a weighted combination of lines changed (50%), files touched (30%), and diff size in bytes (20%). The score is mapped through a curve (sqrt by default) to a time gap:

gap = min_gap + (max_gap - min_gap) * sqrt(score)

A typo fix gets a 10-minute gap. A 500-line refactor gets hours.

Scheduling

Gaps are placed within configurable working hours (default 09:00–17:00, Mon–Fri). When a gap crosses a day boundary, the commit wraps to the next available working day.

Realism engine

Six modifiers make the schedule look human:

Modifier Phase Effect
Holidays Pre-schedule Removes holiday dates (US, UK, CA, etc.)
Days off Pre-schedule Randomly skips ~10% of workdays
Flow state Post-schedule Clusters 2–4 related commits into tight bursts
Late night Post-schedule Moves ~5% of low-complexity commits to 21:00–01:00
Weekend Post-schedule Adds 1–3 commits to ~8% of weekend days
Jitter Post-schedule Random ±5–10 min offset on all timestamps

All modifiers are individually configurable and can be disabled.

Backup and undo

Before rewriting, a standalone git bundle of all refs is created (by default under .git/spreader-backups/<timestamp>.bundle). Unlike a backup ref, a bundle survives git gc, git reset --hard, and even deletion of the repo, and can be moved off-machine. The exact restore command (including your pre-rewrite HEAD) is printed when the rewrite completes:

git fetch .git/spreader-backups/<timestamp>.bundle
git reset --hard <old-HEAD-sha>

Use --bundle-path PATH to choose where the bundle is written, or --no-bundle to skip it (not recommended).

Configuration

Configuration uses a three-tier precedence model: CLI flags > repo .git-spreader.toml > global ~/.config/git-spreader/config.toml > defaults.

Example .git-spreader.toml:

[schedule]
working_hours = { start = "09:00", end = "17:00" }
working_days = ["Mon", "Tue", "Wed", "Thu", "Fri"]
timezone = "America/Los_Angeles"

[realism]
late_night_probability = 0.05
weekend_probability = 0.08
random_day_off_probability = 0.10
flow_state_clustering = true
avoid_holidays = true

[realism.jitter]
min_offset_minutes = -5
max_offset_minutes = 10

[realism.holidays]
calendar = "US"
additional = ["2025-12-24", "2025-12-26"]

[complexity]
weights = { lines = 0.5, files = 0.3, bytes = 0.2 }
min_gap_minutes = 10
max_gap_minutes = 480
curve = "sqrt"  # or "linear", "log"

Development

uv sync
uv run pytest
uv run ruff check src/ tests/
uv run pyright src/

License

Polyform Shield 1.0.0

Metadata

Release files for git-spreader 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for git-spreader 0.3.0
File Size Uploaded
git_spreader-0.3.0.tar.gz 43.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for git-spreader 0.3.0
File Interpreter ABI Platform
git_spreader-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 73.4 kB

Release files / git_spreader-0.3.0.tar.gz

Download URL git_spreader-0.3.0.tar.gz
Size 43.0 kB
Tags Source
SHA-256 checksum
How to use checksums
214fd288836dba16c338182839f660b13e8e30374bebf30fbad6e447f65d3abd
BLAKE2b-256 checksum
How to use checksums
fbff12376c426c36bd61a2af788ef11b933bdd03e6e2e630efc640a87f69cd2a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 30, 2026.

Transparency log

Release files / git_spreader-0.3.0-py3-none-any.whl

Download URL git_spreader-0.3.0-py3-none-any.whl
Size 30.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
dc6ced1c6ea5ab2159fc9dbab2bbd6043a5dd033b63fdd9fe77285754d28ac57
BLAKE2b-256 checksum
How to use checksums
d6bb7bcd814b3f864a81c6fcb38a8db4514e5a3c1dfa56392a440d0b4efcbb34
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 30, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files

0.2.3

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page