Using Emacs vc-diff with tools such as git-crypt or Rails credentials: Handling Binary Diff Issues

Tools like git-crypt or Rails credentials provide an encryption layer for managing sensitive files within Git repositories. However, when using Emacs vc-diff on repositories protected by these tools, the diff output is incorrect because vc-diff compares the encrypted binary files directly rather than comparing the decrypted files. This occurs even when the repository is unlocked and the decrypted content is available, resulting in a failure to display meaningful diffs.

The root cause

Internally, vc-diff uses Git commands to compute diffs. However, it does not invoke them with the --textconv flag by default. Without --textconv, Git does not apply content filters, including decryption filters specified by tools such as git-crypt or Rails credentials. Consequently, Emacs vc-diff displays diffs of the raw binary files rather than the decrypted content.

The solution

A workaround for enabling human-readable diffs of encrypted files in Emacs is to modify the vc-git-diff-switches variable to include the --textconv argument:

;; Emacs vc-diff fails to produce meaningful output on git-crypt enabled
;; repositories because it does not use Git's --textconv flag by default. This
;; flag enables Git to apply text conversion filters (e.g., for encrypted files)
;; when generating diffs. Without it, vc-diff compares raw encrypted blobs, even
;; when the working tree shows decrypted content.
(unless (member "--textconv" vc-git-diff-switches)
  (setq vc-git-diff-switches (cons "--textconv" vc-git-diff-switches)))Code language: Lisp (lisp)

Adding the --textconv flag to the vc-git-diff-switches variable enables Emacs vc-diff to apply the text conversion filters specified in .gitattributes. This resolves the issue by displaying the diff of the decrypted files instead of the encrypted binary files.

Further Reading