Skip to main content

Make 3am commit binges look like responsible adult behavior

Project description

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 config --show    # print effective config
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 backup ref is created at refs/spreader-backup/<timestamp>. To undo:

git reset --hard refs/spreader-backup/<timestamp>

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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

git_spreader-0.2.1.tar.gz (42.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

git_spreader-0.2.1-py3-none-any.whl (27.1 kB view details)

Uploaded Python 3

File details

Details for the file git_spreader-0.2.1.tar.gz.

File metadata

  • Download URL: git_spreader-0.2.1.tar.gz
  • Upload date:
  • Size: 42.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for git_spreader-0.2.1.tar.gz
Algorithm Hash digest
SHA256 290290c9202c95a60486cc82a1b8f02e0e0ce6fac26f13e03bf899bf8a1fff04
MD5 8df81894cb49f11b34156d50b06ea05c
BLAKE2b-256 8650f98f8a9c986bb2ec344ae5b1da18ed9dec044e7e382696f555496549a3b3

See more details on using hashes here.

Provenance

The following attestation bundles were made for git_spreader-0.2.1.tar.gz:

Publisher: publish.yml on lokkju/git-spreader

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file git_spreader-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: git_spreader-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 27.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for git_spreader-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 61d788e8bf24b2a21c42a5978c60c77d0fca0c8832e30240dd7c0d2319c3f87f
MD5 ffdf784f27f1cebd3dfceb148260c552
BLAKE2b-256 ab053ee593df5e2ee5dd3b7ae16f6189b5043872904499b8a17176abaef554f1

See more details on using hashes here.

Provenance

The following attestation bundles were made for git_spreader-0.2.1-py3-none-any.whl:

Publisher: publish.yml on lokkju/git-spreader

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page