Git Encryption

This is about encrypting Git repositories. There are two approaches to consider:

  • encrypt the entire repository
  • encrypt specific files

These approaches are addressed by these tools:

There are other tools that can be used

This gist describes a method to implement file encryption using Git's smudge and clean filters.

Another approach might be to encrypt using Gitolite. Is this possible?

See also


The git-crypt package is available in the Arch Linux AUR is easily built (makepkg -s) and installed:

$ sudo pacman -U git-crypt-0.5.0-3-i686.pkg.tar.xz

Create a test repo:

$ mkdir test && cd test
$ git init
$ git crypt init

Export the symmetric secret key (optional):

$ git crypt export-key /somewhere/safe/test.key

Create a .gitattributes file that lists the files to be encrypted (everything else remains plaintext).

# .gitattributes
private filter=git-crypt diff=git-crypt

Create some secret content

$ echo 'my secret is safe' > private

And some plaintext content

$ echo 'my plaintext' > public

Commit it

$ git add .gitattrbutes private public
$ git commit -m mycommit

That's it. To demonstrate that the content is encrypted:

$ git crypt lock
$ cat public private
my plaintext

Note that locking requires changes to be committed or stashed first. Private files in the stash are encrypted.

To unlock and decrypt:

$ git crypt unlock /somewhere/safe/test.key
$ cat public private 
my plaintext
my secret is safe

To use with GnuPG:

$ git crypt add-gpg-user DEADBEEF

which will commit your public key under .git-crypt/keys/... with a commit message like:

commit a8325a94576de67d358541201e35b9b089901310
Author: Alice <>
Date:   Mon Nov 14 13:32:38 2016 +0000

    Add 1 git-crypt collaborator

    New collaborators:

            DEADBEEF Alice <>

(no files are added to the repository if just using the symmetric key without GnuPG).

Given posession of the private key, there is no need to supply the symmetric key when unlocking:

$ git crypt unlock

Be sure to read the README to understand the limitations. Note especially that

  • git-crypt does not encrypt file names, commit messages, symlink targets, gitlinks, or other metadata.
  • Files encrypted with git-crypt are not compressible. Even the smallest change to an encrypted file requires git to store the entire changed file, instead of just a delta.
  • Files encrypted with git-crypt cannot be patched with git-apply, unless the patch itself is encrypted.


The git-remote-gcrypt package is available in the Arch Linux AUR is easily built (makepkg -s) and installed:

$ sudo pacman -U git-remote-gcrypt-git-1\:1.0.0.r2.gaaa874f-1-any.pkg.tar.xz

Create a test repo:

$ mkdir test && cd test
$ git init

Create and commit some content

$ echo 'my secret is safe' > content
$ git add content
$ git commit -m mycommit

Create encrypted remote

$ git remote add origin gcrypt::git@git:test
$ git push origin master
gcrypt: Repository not found: git@git:test2
gcrypt: Setting up new repository
gcrypt: Remote ID is :id:8t16txPEAnnhqWxioV4Y
gcrypt: Encrypting to: --throw-keyids --default-recipient-self
gcrypt: Requesting manifest signature
gpg: using "DEADBEEF" as default secret key for signing
X11 forwarding request failed on channel 0
To git:test2
 * [new branch]      master -> master

Cloning an encrypted repo is done as follows:

$ git clone gcrypt::git@git:test2

The remote repository is encrypted, the local working copy is not. Be sure to consult the README for further information.

How they work

From what I can gather from a very quick look at the code, git-remote-gcrypt makes an encrypted blob the bare repository (.git tree) and commits that to the remote as an initial commit. The entire repo is encrypted as a single blob on the remote that is decrypted when cloned into a working copy.

In contrast, git-crypt encrypts individual files before they are committed to the repo. They remain encrypted until the repo is unlocked.


Both git-remote-gcrypt and git-crypt can be used together to achive a fully encrypted remote with individally encrypted files in the working copy.