Compare PDFs built from two git commits by running a user-provided build command.
Project description
diff-pdf-commits
Compare PDFs produced by two Git revisions.
diff-pdf-commits creates temporary detached worktrees for two refs, runs your PDF build command in each worktree, copies the requested PDF artifacts, and optionally runs diff-pdf to produce a visual diff.
It is intentionally build-system agnostic. Use it with LaTeX, Typst, Make, Task, Docker Compose, or any other command that can build a PDF from a checked-out Git tree.
Features
- Builds the same PDF from two Git refs without changing your current checkout.
- Uses
git worktreeinstead ofgit checkout, so your working tree is not mutated. - Accepts any shell build command through
--build. - Exports both generated PDFs for inspection.
- Can save a visual diff PDF with
diff-pdf. - Can open the
diff-pdfGUI viewer. - Supports extra build environment variables with
--env. - Supports copying local ignored files, such as
.env, into both worktrees with--copy. - Refuses dirty worktrees by default, with an explicit
--dirty allowoverride.
Installation
Run directly with uvx:
uvx diff-pdf-commits HEAD~1 HEAD \
--build "latexmk -pdf main.tex" \
--pdf main.pdf
Install it with pipx:
pipx install diff-pdf-commits
Install it with pip:
python -m pip install diff-pdf-commits
Run from a local checkout:
uvx --from . diff-pdf-commits HEAD~1 HEAD \
--build "make pdf" \
--pdf build/main.pdf
Run from GitHub source:
uvx --from git+https://github.com/ethercod3/diff-pdf-commits diff-pdf-commits HEAD~1 HEAD \
--build "make pdf" \
--pdf build/main.pdf
Requirements
Required:
- Python 3.10+
- Git
- The tools needed by your build command
Optional:
diff-pdfonPATHfor visual comparisonuvif you want to run the package withuvx
diff-pdf is not required when using --no-diff; in that mode the command only builds both revisions and exports the generated PDFs.
Usage
Save a visual diff PDF:
diff-pdf-commits HEAD~1 HEAD \
--build "latexmk -pdf main.tex" \
--pdf main.pdf
Only build both revisions and export the PDFs:
diff-pdf-commits v1.0.0 HEAD \
--build "typst compile main.typ main.pdf" \
--pdf main.pdf \
--no-diff
Open the diff-pdf viewer:
diff-pdf-commits main feature/report-layout \
--build "make pdf" \
--pdf build/report.pdf \
--view
Write the visual diff to a specific path:
diff-pdf-commits HEAD~1 HEAD \
--build "task pdf" \
--pdf dist/report.pdf \
--diff-output review/report-diff.pdf
Pass environment variables to the build:
diff-pdf-commits HEAD~1 HEAD \
--build "task pdf" \
--pdf report.pdf \
--env TEXMFVAR=.tex-cache \
--env SOURCE_DATE_EPOCH=0
Copy local files into both worktrees before building:
diff-pdf-commits HEAD~1 HEAD \
--build "task pdf" \
--pdf report.pdf \
--copy .env \
--copy config/local.json
Allow a dirty current worktree:
diff-pdf-commits HEAD~1 HEAD \
--build "make pdf" \
--pdf build/main.pdf \
--dirty allow
Keep temporary worktrees for debugging:
diff-pdf-commits HEAD~1 HEAD \
--build "make pdf" \
--pdf build/main.pdf \
--keep-worktrees
Output
By default, artifacts are written under .pdf-diff/<left>__<right>/:
.pdf-diff/
HEAD_1__HEAD/
logs/
build-left.log
build-right.log
pdfs/
left-HEAD_1-main.pdf
right-HEAD-main.pdf
worktrees/
left/
right/
Temporary worktrees are removed after the run unless --keep-worktrees is passed. Build logs and copied PDFs are kept.
Command Reference
Usage: diff-pdf-commits [OPTIONS] LEFT_REF RIGHT_REF
Options:
--build TEXT Shell command that builds the PDF in each worktree.
--pdf PATH PDF path relative to repo root.
--repo PATH Path inside the git repository.
--out PATH Output directory.
--diff-output PATH Write visual diff PDF to this path.
--view / --no-view Open diff-pdf GUI viewer.
--no-diff Only build and export both PDFs; do not run diff-pdf.
--keep-worktrees Keep temporary git worktrees for debugging.
--dirty [fail|allow] Refuse or allow a dirty current worktree.
--env KEY=VALUE Environment variable passed to the build command.
--copy PATH Copy a local file or directory into each worktree.
-h, --help Show help.
There is also a pdf-commit-diff console script that points to the same command.
Security
--build is executed as a shell command in each temporary worktree. This is deliberate, because real PDF projects commonly use commands such as make pdf, task pdf, latexmk, typst, or docker compose.
Do not pass untrusted build strings.
Development
uv sync --extra dev
uv run black --check --diff src tests
uv run pytest
Docker-based integration tests are opt-in:
DIFF_PDF_COMMITS_RUN_DOCKER_TESTS=1 uv run pytest
Run the local checkout through uvx:
uvx --from . diff-pdf-commits HEAD~1 HEAD --build "make pdf" --pdf build/main.pdf
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 diff_pdf_commits-0.1.0.tar.gz.
File metadata
- Download URL: diff_pdf_commits-0.1.0.tar.gz
- Upload date:
- Size: 40.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b3ffa5767caeafcea4c4c3571254d1208a99b3574ee8914853056d747e18a21c
|
|
| MD5 |
b7d8f0d8579157c2b0b2039be3181489
|
|
| BLAKE2b-256 |
a2aa2670809fa625db135d1d0bc280fb63ba57a140eedcbac4c438100587edcd
|
Provenance
The following attestation bundles were made for diff_pdf_commits-0.1.0.tar.gz:
Publisher:
publish.yml on ethercod3/diff-pdf-commits
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
diff_pdf_commits-0.1.0.tar.gz -
Subject digest:
b3ffa5767caeafcea4c4c3571254d1208a99b3574ee8914853056d747e18a21c - Sigstore transparency entry: 1668012243
- Sigstore integration time:
-
Permalink:
ethercod3/diff-pdf-commits@c3d6c497d43e785feaf0a5dbc6f7185189a01ef8 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/ethercod3
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@c3d6c497d43e785feaf0a5dbc6f7185189a01ef8 -
Trigger Event:
release
-
Statement type:
File details
Details for the file diff_pdf_commits-0.1.0-py3-none-any.whl.
File metadata
- Download URL: diff_pdf_commits-0.1.0-py3-none-any.whl
- Upload date:
- Size: 11.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eb844c1bbcba6a66527696b6c2613115f464abe733c786866b582b3e601ffaa5
|
|
| MD5 |
4eb247701c149eb7df426188901e1b05
|
|
| BLAKE2b-256 |
f74aefeb23fcfc212a2116e846476d4e81f0cb94cdc592711d67801832efbcbd
|
Provenance
The following attestation bundles were made for diff_pdf_commits-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on ethercod3/diff-pdf-commits
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
diff_pdf_commits-0.1.0-py3-none-any.whl -
Subject digest:
eb844c1bbcba6a66527696b6c2613115f464abe733c786866b582b3e601ffaa5 - Sigstore transparency entry: 1668012404
- Sigstore integration time:
-
Permalink:
ethercod3/diff-pdf-commits@c3d6c497d43e785feaf0a5dbc6f7185189a01ef8 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/ethercod3
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@c3d6c497d43e785feaf0a5dbc6f7185189a01ef8 -
Trigger Event:
release
-
Statement type: