{"slug": "translate-git-commit-messages-offline-without-rewriting-code", "title": "Translate Git Commit Messages Offline Without Rewriting Code", "summary": "An open-source Python CLI, git-translate-commits, enables developers to preview and normalize Git commit messages offline using a local translation engine, avoiding the privacy risks of external APIs. The tool uses Argos Translate to convert mixed-language commits into a single target language without requiring an API key, helping teams maintain consistent, searchable commit histories.", "body_md": "A repository can have clean code and still have a difficult history. One commit says `fix: corrige timeout`\n\n, another says `feat: add retry logic`\n\n, and the next was generated by an AI coding assistant in a third language.\n\nThat inconsistency makes `git log`\n\n, release-note preparation, blame investigation, and onboarding harder than they need to be. Manually editing hundreds of messages is not realistic, while sending an entire private history to an external translation API may violate your team's privacy expectations.\n\nThis tutorial shows how to use [git-translate-commits](https://github.com/paladini/git-translate-commits), an open-source Python CLI, to preview and normalize Git commit messages with a local translation engine. We will test the operation in a disposable clone first because changing a commit message necessarily changes its commit hash.\n\nInstall the CLI, create a disposable clone, and start with:\n\n```\ngit-translate-commits --lang en --dry-run\n```\n\nThe default engine uses Argos Translate. It downloads the required language model on first use and can then translate locally without an API key. Do not remove `--dry-run`\n\nuntil you have inspected the proposed messages and coordinated any history rewrite with everyone using the repository.\n\nMixed-language commits are not inherently wrong. The problem appears when a team expects one searchable language but people, automation, and coding agents produce several.\n\nConsider a production incident. You search for \"payment timeout\", but the relevant fix was committed as `corrige tempo limite do pagamento`\n\n. Git cannot retrieve the concept if the words do not match. The same inconsistency affects changelog generation and tools that classify Conventional Commits.\n\nThe safest time to establish a commit-language policy is before merging. Existing repositories, however, may already contain years of mixed messages. A controlled history rewrite can normalize that history, provided the team understands the consequences.\n\nThe current package metadata requires Python 3.10 or newer. You also need Git and either `pipx`\n\n, `uv`\n\n, or `pip`\n\n.\n\nInstall the command in an isolated environment:\n\n```\npipx install git-translate-commits\n\n# Alternative with uv\nuv tool install git-translate-commits\n```\n\nThe published PyPI package is currently version `1.0.1`\n\n. During verification for this tutorial, the installed command responded to `--version`\n\n, although it printed `v1.0.0`\n\n. Treat PyPI metadata as the package-release version until that CLI display mismatch is corrected.\n\nDo not test a history-rewriting tool in your only local copy. Clone the repository into a separate directory and keep the original remote unchanged:\n\n```\ngit clone https://github.com/your-org/your-repository.git history-translation-test\ncd history-translation-test\ngit status\n```\n\nReplace the placeholder URL with a repository you are authorized to modify. Confirm that the working tree is clean before continuing.\n\nFor a shared repository, announce the experiment before anybody bases new work on rewritten commits. Even a correct rewrite creates new commit identifiers.\n\nThe required option is `--lang`\n\n. Use a language code such as `en`\n\n, `es`\n\n, or `pt-BR`\n\n.\n\nRun the default local engine in dry-run mode:\n\n```\ngit-translate-commits --lang en --dry-run\n```\n\nThis is the critical safety step. `--dry-run`\n\nshows what would change without modifying the repository.\n\nReview the preview for:\n\n`#123`\n\n;`feat:`\n\nand `fix:`\n\n;By default, the CLI is documented to skip messages already detected in the target language and preserve Conventional Commit prefixes.\n\nYou rarely need to translate everything on the first attempt. Filters make a smaller experiment easier to review.\n\nFor example, preview commits from a date forward:\n\n```\ngit-translate-commits \\\n  --lang en \\\n  --since \"2026-01-01\" \\\n  --dry-run\n```\n\nYou can also select an author:\n\n```\ngit-translate-commits \\\n  --lang en \\\n  --author \"developer@example.com\" \\\n  --dry-run\n```\n\nOther documented filters include `--until`\n\n, `--branch`\n\n, and `--all-branches`\n\n. Start with the current branch unless you have a reviewed migration plan for the entire repository.\n\ngit-translate-commits changes commit messages rather than source files. Its documented preservation rules include:\n\n`Co-authored-by`\n\nand `Signed-off-by`\n\n.Preserving those fields does not preserve commit hashes. A commit hash incorporates the commit message, so changing the message produces a different hash. Every descendant commit is rewritten as well.\n\nThe CLI creates a backup branch by default and writes `.git-translate-log.json`\n\nwith the old-to-new mapping. Keep both until the rewritten history has been reviewed.\n\nOnce the dry run is correct and the team has agreed on the migration window, run the same command without `--dry-run`\n\n:\n\n```\ngit-translate-commits --lang en\n```\n\nThe command asks for confirmation unless `--force`\n\nis used. Avoid `--force`\n\nduring an initial migration because the prompt is a useful final pause.\n\nAfter the command completes, inspect the result locally:\n\n```\ngit log --oneline --decorate -n 20\ngit branch --list\ngit status\n```\n\nCompare representative messages with the preview, confirm that the backup branch exists, and inspect `.git-translate-log.json`\n\n.\n\nDo not force-push immediately. Run your tests and compare the rewritten tree with the original branch first. The file trees should remain equivalent even though commit hashes differ.\n\nThe default local engine is the privacy-oriented path. The project also offers an optional `llm`\n\nextra through LiteLLM:\n\n```\npipx install \"git-translate-commits[llm]\"\ngit-translate-commits --lang en --engine llm\n```\n\nThis mode can use OpenAI, Anthropic, or an OpenAI-compatible provider. It changes the privacy, cost, and credential boundaries of the workflow. Prefer environment variables over command-line API keys, and confirm whether commit messages are allowed to leave your environment.\n\nAn OpenAI-compatible local server can provide a different local path, but model behavior and compatibility depend on that server. Validate it separately rather than assuming it behaves like the default Argos engine.\n\nBefore rewriting, record the tree hash of the branch tip:\n\n```\ngit rev-parse HEAD^{tree}\n```\n\nRun the same command after translation. If the tree hash is identical, the checked-in file snapshot at the branch tip is unchanged. This does not replace tests, but it is a useful deterministic check that the final source tree stayed the same.\n\nAlso verify:\n\nHistory rewriting is disruptive. Open pull requests, signed commits, release tags, CI references, and external links to commits can be affected. A backup branch helps recovery, but it does not remove the coordination cost.\n\nFor an active public repository, keeping existing history and enforcing one language only for future commits may be the better choice. A commit-message hook, contribution guideline, or pull-request squash policy can prevent new drift without invalidating old hashes.\n\nLocal neural translation also has quality limits. Domain-specific messages may need manual review. The optional LLM engine may improve context in some cases, but it introduces a provider and a data-transfer boundary.\n\nNo. The tool targets Git commit messages. You should still compare tree hashes and run tests before sharing rewritten history.\n\nYes. Use `--dry-run`\n\n, and keep it enabled while tuning language, branch, author, and date filters.\n\nYes. The message is part of the commit object, so changing it creates a new hash.\n\nNo. The default Argos Translate engine downloads language data on first use and operates locally afterward.\n\nOnly with explicit team coordination and a recovery plan. For many active repositories, a future-only commit-language policy is safer.\n\nA consistent Git history is useful, but consistency is not worth a surprise rewrite. Start in a disposable clone, use the offline dry run, narrow the scope, verify tree hashes, and involve the team before changing a shared branch.\n\ngit-translate-commits turns a repetitive editing problem into a reviewable workflow. The most important feature is not automatic translation. It is the ability to inspect the plan before accepting a destructive change.\n\nDisclosure: This article was researched, fact-checked, and drafted with AI assistance using the current primary project sources linked above.\n\nWould you rewrite an existing multilingual history, or enforce one commit language only from today forward?", "url": "https://wpnews.pro/news/translate-git-commit-messages-offline-without-rewriting-code", "canonical_source": "https://dev.to/paladini/translate-git-commit-messages-offline-without-rewriting-code-49he", "published_at": "2026-07-28 19:45:07+00:00", "updated_at": "2026-07-28 20:01:59.008086+00:00", "lang": "en", "topics": ["developer-tools", "natural-language-processing"], "entities": ["git-translate-commits", "Argos Translate", "PyPI", "Git"], "alternates": {"html": "https://wpnews.pro/news/translate-git-commit-messages-offline-without-rewriting-code", "markdown": "https://wpnews.pro/news/translate-git-commit-messages-offline-without-rewriting-code.md", "text": "https://wpnews.pro/news/translate-git-commit-messages-offline-without-rewriting-code.txt", "jsonld": "https://wpnews.pro/news/translate-git-commit-messages-offline-without-rewriting-code.jsonld"}}