GI

git-crypt

Transparent file encryption for secrets stored in git

Password Managers ★ 9.9k stars Easy setup GPL-3.0

git-crypt is an open-source tool that enables transparent encryption and decryption of files in a git repository. Files you choose are encrypted when committed and decrypted when checked out, keeping secrets safe in version control.

Key features

  • Transparent file encryption in git
  • GPG-based key management
  • Selective encryption via gitattributes
  • No server required

Pros & cons

Strengths

  • Simple to integrate with git
  • Keeps secrets in repos safely

Trade-offs

  • Not a vault with access control

git-crypt replaces

Last reviewed Aug 26, 2026 · 823 words

git-crypt solves exactly one problem: you want secrets.env in the same repository as the compose file that reads it, and you do not want it readable on the remote. It does that in 5 commands and about 32 MB of memory, with no server and nothing to keep running. It does not do access control, rotation, expiry or audit, and the day you need to remove a collaborator is the day you learn why the catalogue's only listed con, "not a vault with access control", is the important sentence on the page.

Five commands from plaintext to encrypted

sudo apt install git-crypt          # brew install git-crypt on macOS
cd ~/homelab
git-crypt init
printf 'secrets/** filter=git-crypt diff=git-crypt\n*.env filter=git-crypt diff=git-crypt\n' >> .gitattributes
git-crypt add-gpg-user [email protected]
git add .gitattributes && git commit -m "Encrypt secrets with git-crypt"

From here, files matching the patterns are encrypted on commit and decrypted on checkout, and the working tree looks exactly as it did before. git-crypt status lists which files are encrypted and which are not. On a fresh clone, git-crypt unlock decrypts using your GPG key; git-crypt lock re-encrypts the working copy when you step away from a shared machine. For a CI runner with no GPG, git-crypt export-key ./repo.key produces the raw symmetric key that git-crypt unlock ./repo.key accepts, which is convenient and is also a file you now have to protect as carefully as the secrets themselves.

What is actually happening underneath

git-crypt is a Git clean/smudge filter. Each repository gets one random symmetric key, files are encrypted with AES-256 in CTR mode with an HMAC over the contents, and that key is stored inside .git-crypt/keys/ once per authorised user, encrypted to their GPG public key. Encryption is deterministic, so an unchanged file produces identical ciphertext and Git can still tell whether it changed. The diff=git-crypt attribute means git diff shows plaintext changes when the repository is unlocked. The design has not changed much since 2013, which is a compliment: it is small, C++, and does one thing without surprises.

The trap: you cannot un-add a user

Removing someone means generating a new key and re-encrypting the files, and anything already pushed remains decryptable by every key that ever had access, forever, in history. The honest procedure when a collaborator leaves is not "remove them from git-crypt"; it is "rotate every secret in the repository" and then re-key. A second, quieter trap: any file committed before its pattern went into .gitattributes is plaintext in history for good. Run git-crypt status immediately after adding patterns, and if it lists a file you already committed, treat that secret as burned and change it.

Where it sits next to Vaultwarden, Infisical and Vault

These are three different jobs. Vaultwarden is for human passwords and logins, with apps and browser extensions; it is not for DATABASE_URL. Infisical and Vault are runtime secret stores: applications fetch credentials at start, access is per-user and per-path, everything is logged, and revoking someone is one click that actually works. They cost a running service, a database and an evening of setup. git-crypt is what you use when the "team" is 1 to 3 people, the secrets are a few .env files in a homelab repository, and the threat is the remote being read rather than a colleague going rogue. If per-value encryption with readable diffs appeals, SOPS with age keys is the more modern tool in the same class; git-crypt's advantage is being invisible once configured.

Where it earns its place in a homelab

The pattern that works: one repository with every compose file, a secrets/ directory encrypted with git-crypt, and env_file: secrets/immich.env lines in the services. Pushed to a private forge, the repository is a complete, restorable description of the server, and a fresh box needs only a clone, a GPG key and git-crypt unlock to rebuild. The compose patterns post covers the rest of that layout; git-crypt is the piece that makes committing it safe.

What I'd do

Use git-crypt for the homelab repository and for any project with fewer than 4 people who can push. Add the .gitattributes patterns in the very first commit, before a single secret exists, and keep an exported key in your password manager as the disaster copy. The moment a fourth person joins, a secret must rotate on a schedule, or anyone asks who accessed what, move the secrets into Infisical and leave git-crypt for the config files that never mattered much anyway. It is a good tool with hard edges, and the edges are all about people, not cryptography.

Compare git-crypt

5 head-to-head comparisons.

Similar password managers apps