Skip to main content

Compare PDFs built from two git commits by running a user-provided build command.

Project description

diff-pdf-commits

CI PyPI Python License: MIT Run with uvx

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 worktree instead of git 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-pdf GUI 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 allow override.

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-pdf on PATH for visual comparison
  • uv if you want to run the package with uvx

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

Load project defaults from a TOML config:

diff-pdf-commits HEAD~1 HEAD --config diff_config.toml

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.

Config File

Use --config when a repository needs a repeatable build command, environment, copied local files, or a PDF name derived from TARGET.

[diff_pdf]
build = "docker compose --profile latex run --build --rm latex"
env_file = ".env"
pdf_from_target = true
view = true

[diff_pdf.env]
PYTHONIOENCODING = "utf-8"
PYTHONUTF8 = "1"
TARGET = { from_env = "TARGET" }
VAULT_PATH = { from_env = "VAULT_PATH" }
VAULT_OS_PATH = { from_env = "VAULT_OS_PATH", resolve = true }

[diff_pdf.copy]
paths = [
  ".env",
  "docker-compose.yaml",
  "docker/latex.dockerfile",
]

Supported [diff_pdf] keys:

  • build: shell command to run in each worktree.
  • pdf: PDF path, or { from_env = "TARGET", replace_suffix = ".pdf" }.
  • pdf_from_target: shorthand for deriving the PDF path from TARGET.
  • env_file: optional .env-style file used for config expansion.
  • out, diff_output, view, no_diff, keep_worktrees, dirty.
  • [diff_pdf.env]: build environment values. Values may be strings or { from_env = "...", default = "...", resolve = true }.
  • [diff_pdf.copy] paths: files or directories copied into both worktrees before building.

Command-line options override config values. Repeated --env values override matching [diff_pdf.env] keys; repeated --copy values are appended.

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


Download files

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

Source Distribution

diff_pdf_commits-0.1.1.tar.gz (43.4 kB view details)

Uploaded Source

Built Distribution

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

diff_pdf_commits-0.1.1-py3-none-any.whl (14.3 kB view details)

Uploaded Python 3

File details

Details for the file diff_pdf_commits-0.1.1.tar.gz.

File metadata

  • Download URL: diff_pdf_commits-0.1.1.tar.gz
  • Upload date:
  • Size: 43.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for diff_pdf_commits-0.1.1.tar.gz
Algorithm Hash digest
SHA256 178111d0d7889ff425821a30c22d38c7ad212cfa30730b94a2d7add3083e099b
MD5 3deab04c0e3dc26730ac148a6ca802a5
BLAKE2b-256 9b6fe04d196d6c66255ccc2bdb37e4a980aad04fa29e14931b8cb7631eeb8ab1

See more details on using hashes here.

Provenance

The following attestation bundles were made for diff_pdf_commits-0.1.1.tar.gz:

Publisher: publish.yml on ethercod3/diff-pdf-commits

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

File details

Details for the file diff_pdf_commits-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for diff_pdf_commits-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 174f0cbfd75a4144b5a2c2de0c51ae4c607b9f7a086bf5ca3f5c7b63da34ad38
MD5 4d429136c1248b5adb763fb70bd21645
BLAKE2b-256 49d3d81c3e76a61f8646a0a5b9e6ee55d12ae81058d9e872f965c91a57a6b01f

See more details on using hashes here.

Provenance

The following attestation bundles were made for diff_pdf_commits-0.1.1-py3-none-any.whl:

Publisher: publish.yml on ethercod3/diff-pdf-commits

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