Rewrite git commit timestamps to fit within or exclude certain time windows
Project description
git-alibi
Rewrite git commit timestamps to fit within (or avoid) configured time windows.
Useful for keeping commit history clean when you work odd hours, across timezones, or want commits to consistently appear within business hours. Alibi saves a backup before every rewrite so changes can always be undone.
Requirements
- Python 3.11 or newer
- git 2.25 or newer
Installation
pip (simplest):
cd git-alibi
pip install .
pipx (isolated, recommended for CLI tools):
pipx install /path/to/git-alibi
Virtual environment (if you prefer not to touch system Python):
cd git-alibi
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install .
Verify the install:
git-alibi --help
# git also picks it up automatically:
git alibi --help
Uninstallation
pip uninstall git-alibi # if installed with pip
pipx uninstall git-alibi # if installed with pipx
rm -rf .venv # if installed into a venv, just delete it
Quick start
Preview what would change without touching the repo:
git-alibi rewrite --dry-run
Apply the rewrite:
git-alibi rewrite
If the branch was already pushed:
git push --force-with-lease
Undo the last rewrite:
git-alibi restore
Configuration
Alibi is configured with TOML files. Settings in the local file take precedence over the global one.
| File | Scope |
|---|---|
~/.config/alibi/config.toml |
Global (all repos) |
.git/alibi/config.toml |
Local (this repo only) |
Open a config file in $EDITOR (created with commented-out defaults if it doesn't exist):
git-alibi config local
git-alibi config global
Example config
[behavior]
timezone = "America/Chicago"
out_of_window = "nearest" # nearest / previous / next / random
spacing = "preserve" # preserve / proportional / even / random
[days]
block = ["SAT", "SUN"] # never place commits on weekends
[times]
allow = ["09:00-17:00"] # only allow commits during business hours
[authors]
# CURRENT expands to the email in git config user.email
emails = ["CURRENT"]
[markers]
# Commits containing this string in their message are never rewritten
skip = ["[no-alibi]"]
Commands
rewrite
Rewrites commit timestamps to fit within the configured windows. Operates on
commits in the current branch since it diverged from main/master (or the
upstream tracking branch), for the current git user's commits only.
git-alibi rewrite [OPTIONS] [REF]
| Option | Description |
|---|---|
--dry-run |
Preview changes without modifying the repo |
-v, --verbose |
Show all commits in dry-run output, not just changed ones |
--no-backup |
Skip saving a backup before rewriting |
--shift DURATION |
Shift timestamps by a fixed amount instead of fitting windows (e.g. +2h, -5h30m, +5:30) |
--timezone TZ |
Override the timezone (IANA name, e.g. America/Chicago) |
--allow-days DAYS |
Comma-separated days to allow (e.g. MON,TUE,WED,THU,FRI) |
--block-days DAYS |
Comma-separated days to block (e.g. SAT,SUN) |
--allow-times RANGES |
Time ranges to allow (e.g. 09:00-17:00, MON+FRI@09:00-12:00) |
--block-times RANGES |
Time ranges to block |
--allow-dates DATES |
Dates or ranges to allow (e.g. 2024-03-01:2024-03-31) |
--block-dates DATES |
Dates or ranges to block (e.g. 2024-12-25) |
--out-of-window |
How to handle commits outside all windows: nearest (default), previous, next, random |
--spacing |
How to distribute commits within a window: preserve (default), proportional, even, random |
--author-emails EMAILS |
Comma-separated emails to rewrite; CURRENT = git config user.email |
--all-authors |
Rewrite commits by all authors, not just the current user |
--all-history |
Rewrite all reachable history, not just the current branch |
--skip-markers MARKERS |
Comma-separated message markers that exempt a commit (default: [no-alibi]) |
-f, --force |
Proceed even if signed commits would be rewritten |
Timezone correction with --shift
If you committed in the wrong timezone, shift all timestamps by a fixed offset:
git-alibi rewrite --shift +5:30 # move everything forward 5h30m
git-alibi rewrite --shift -8h # move everything back 8 hours
git-alibi rewrite --dry-run --shift +2h # preview first
Opting out of rewriting
Add [no-alibi] anywhere in a commit message to permanently exempt that commit:
fix: correct off-by-one error [no-alibi]
The marker string is configurable via [markers] skip in the config file or
--skip-markers on the command line.
restore
Restores commit timestamps from the backup saved before a previous rewrite.
git-alibi restore [OPTIONS] [REF]
| Option | Description |
|---|---|
--dry-run |
Preview what would be restored without applying |
-v, --verbose |
Show all commits, not just changed ones |
--last N |
Undo the Nth most recent rewrite (default: 1 = last) |
--rewrite ID |
Restore a specific rewrite by ID (see history) |
-f, --force |
Proceed even if signed commits would be rewritten |
git-alibi restore # undo the last rewrite
git-alibi restore --last 2 # undo the second-to-last rewrite
git-alibi restore --rewrite 3 # restore to a specific snapshot ID
history
Shows all recorded rewrites and the exact command to restore each one.
git-alibi history [-v]
Rewrite history — 3 snapshots in .git/alibi/backup.json
ID WHEN COMMITS --last RESTORE
───────────────────────────────────────────────────────
1 2024-01-06 Sat 09:15:00 5 3 alibi restore --last 3
2 2024-01-07 Sun 14:30:00 3 2 alibi restore --last 2
3 2024-01-08 Mon 11:15:00 2 1 alibi restore ← latest
Use -v to also list the individual commits and their original timestamps.
config
Opens a config file in $EDITOR, creating it with commented-out defaults if it
doesn't exist yet.
git-alibi config local # .git/alibi/config.toml
git-alibi config global # ~/.config/alibi/config.toml
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file git_alibi-0.1.0.tar.gz.
File metadata
- Download URL: git_alibi-0.1.0.tar.gz
- Upload date:
- Size: 47.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1509acf1a15b22233458e88d0999d56e641cedfe9ae05354dcc02c07447b1521
|
|
| MD5 |
2f264b59403ab41fe77213ab4238550a
|
|
| BLAKE2b-256 |
3cc0f6f34b1819acffd142a3567425fb203e8f814f778e4ff47d8f0faf3ee032
|
File details
Details for the file git_alibi-0.1.0-py3-none-any.whl.
File metadata
- Download URL: git_alibi-0.1.0-py3-none-any.whl
- Upload date:
- Size: 35.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
af4db6164b89c7f2fdaedd01e3b8f7fe9b09b2574608bb8c13b279c0dcfb1872
|
|
| MD5 |
46827f9ba0b3f073186c8e7e3c5aaba4
|
|
| BLAKE2b-256 |
f2eeb8a41c5c69b0c6c6bfc6f3946354df7cbcb908685fa27cf35f813f769933
|