TL;DR
Mixed-language commit histories make changelogs, release notes, and repository archaeology harder to scan. git-translate-commits is a Python CLI that translates commit messages to a target language. Its default engine is local Argos Translate, so the documented offline path does not require an API key.
This tutorial uses the stable v1.0.1 release to build a cautious workflow: install the tool in an isolated environment, preview the changes, restrict the commit range when useful, and only then decide whether rewriting history is appropriate.
Prerequisites
You need:
- Python 3.10 or newer.
- Git installed and available on your
PATH. - A local clone of a repository whose history you are allowed to rewrite.
-
pipx,uv, or another isolated Python installation method.
The project is released under GPL-3.0-or-later. The commands below target the published 1.0.1 package and the matching Git tag, not an unreleased default-branch change.
Install the CLI in isolation
The project README recommends pipx or uv for CLI installation. pipx keeps the application's dependencies out of the rest of your Python environment:
pipx install git-translate-commits==1.0.1
You can verify the installed version without touching a repository:
git-translate-commits --version
The package metadata declares the console entry point git-translate-commits and requires Python 3.10 or newer. The default dependencies include Argos Translate, GitPython, language detection, Rich, and python-dotenv.
Preview a translation without rewriting history
Change into a disposable clone or a repository where you have permission to work. Start with the documented dry-run command:
cd path/to/your-repository
git-translate-commits --lang en --dry-run
The --lang option is required. The --engine option defaults to local, and --dry-run reports what would change without applying a rewrite. The local engine may download a language pack on first use. After that initial download, translation is designed to run offline.
If your current branch contains only English messages, a dry run may report that there is nothing to do. That is still a useful result: it confirms the repository can be read and that the selected language detector does not identify work unnecessarily.
For a more controlled preview, narrow the input. For example, this checks commits after a date and only for one author:
git-translate-commits \
--lang en \
--since "2025-01-01" \
--author "dev@example.com" \
--dry-run
The CLI also supports --until, repeatable --branch, and --all-branches. These filters are useful when you are cleaning a recent slice of history rather than attempting to process every ref.
Choose the local engine deliberately
The local engine is the safest starting point for a repository containing unpublished work. It uses Argos Translate instead of sending messages to an external API:
git-translate-commits --lang pt-BR --engine local --dry-run
That does not mean the tool has no external activity ever. Argos language packs are downloaded automatically when first needed, and the package itself comes from the Python package index during installation. Once the required language data is available, the documented local translation path is intended to operate without an API key.
The project also provides an optional LLM engine through the llm extra. It supports OpenAI, Anthropic, and OpenAI-compatible providers through LiteLLM:
pipx install "git-translate-commits[llm]==1.0.1"
git-translate-commits --lang en --engine llm --provider openai --model gpt-4o-mini --dry-run
Use the LLM path only when its data handling and cost are acceptable for your commit history. The README documents OPENAI_API_KEY and ANTHROPIC_API_KEY environment variables. Never place a real key directly in a committed script or shared shell history.
Apply a rewrite only after review
If the dry-run report is correct and the repository is ready for a history rewrite, run the same selection without --dry-run:
git-translate-commits --lang en --engine local
The default behavior creates a backup branch before rewriting. You can inspect the available safety controls with:
git-translate-commits --help
The CLI exposes --backup/--no-backup, --force, and --preserve-conventional/--no-preserve-conventional. The default preserves Conventional Commit prefixes such as feat: and fix:. The project also documents a JSON log containing the original and translated mapping.
For a shared repository, coordinate before force-pushing. Commit messages are part of Git commit objects, so changing them changes commit hashes. Existing branches, open pull requests, signed commits, release references, and downstream clones may need attention after the rewrite.
Verify the result
After a real rewrite, inspect the backup branch and compare the history before considering any push:
git branch --list "backup/pre-rewrite-*"
git log --oneline --decorate -n 20
git diff --stat "backup/pre-rewrite-*" HEAD
The exact backup branch name includes a timestamp, so replace the wildcard with the name printed by the tool when running commands that require one exact ref. Also inspect the generated .git-translate-log.json file if the run produced it. It provides a reviewable mapping instead of requiring you to infer every change from the new hashes.
If the result is wrong, stop before pushing. The backup branch is the recovery point documented by the project. A local history rewrite is reversible only while you still have an intact reference to the old commits.
Why this workflow works
There are three separate decisions here. First, language selection determines the intended output. Second, the engine determines whether messages remain local or are sent through an LLM provider. Third, the rewrite step changes immutable Git history. Keeping those decisions separate makes the process easier to review.
The tool also preserves more than a one-line subject. The README says it preserves file contents, author and committer metadata, timestamps, Conventional Commit prefixes, issue references, and Git trailers such as Signed-off-by. Translation changes the message text, but it is not intended to rewrite the files in each commit.
The v1.0.1 checkout includes a test suite. I ran it from a clean checkout with the source package available on PYTHONPATH: all 43 tests passed. That verifies the checked-out package behavior, but it is not a guarantee that every repository or language pair will produce a good translation.
Failure modes and honest limits
The history is not clean
The pipeline refuses to rewrite a repository with uncommitted changes unless it is running in dry-run mode. Commit or stash changes first, or use a disposable clone.
A language pack is unavailable
The local engine may need to download a language pack. Plan for that first-run network step, and verify that the requested language pair is supported before a large run.
Translation quality is not uniform
Commit messages contain abbreviations, product names, issue identifiers, code symbols, and project-specific vocabulary. Review the dry-run output. The local engine is useful for normalization, not a substitute for a human review of important release history.
Rewriting can disrupt collaborators
Changing commit messages changes hashes. Do not force-push a shared branch casually, and remember that a backup branch on your machine does not automatically protect every remote clone.
LLM mode changes the privacy boundary
The optional LLM engine can send commit content to the configured provider. Use local mode when messages may contain confidential names, incident details, customer references, or unreleased plans.
FAQ
Does the default mode require an API key?
No. The documented default is the local Argos Translate engine. It may download language data on first use, but it does not require an LLM API key.
Can I translate only one branch or author?
Yes. Use --branch, --author, --since, and --until to constrain the selection. Use --all-branches when you intentionally want all local branches processed.
Does it change source files?
The project documents preservation of file contents. The operation rewrites commit messages and therefore commit hashes, not the snapshots represented by those commits.
Should I use this on a public repository?
Only with a reviewed migration plan. A public history rewrite can break links, signatures, forks, pull requests, and consumers that refer to old hashes.
Takeaway
git-translate-commits is most useful when language consistency is worth a controlled history migration. Start with v1.0.1, use the local engine, preview with --dry-run, keep the automatic backup, and review the log before changing a shared ref.
Have you ever normalized a mixed-language Git history, and which preservation rule mattered most in your repository?
AI assistance disclosure
AI assistance was used to help organize and edit this tutorial. The commands, version details, license, documented behavior, and test result were checked against the public v1.0.1 source, README, package metadata, and a clean checkout of the project.
Top comments (0)