Git Can Diff Your Encrypted Rails Credentials
I edited an encrypted credentials file and ran git diff expecting gibberish. Instead I got a clean, readable YAML diff. Here is how Rails does it.
I changed a key in my encrypted credentials file today. When I ran git diff afterwards, I expected to see a wall of base64 noise. Instead, I got this:
+some_api:
+ secret_key: sekrit_123
nuclear_launch_code: 54321
wifi_password: password
A perfectly readable YAML diff of the decrypted content. I did not set this up. Rails did.
How it works
There are two pieces. The first is a line in .gitattributes at the root of your Rails app:
config/credentials/*.yml.enc diff=rails_credentials
config/credentials.yml.enc diff=rails_credentials
This tells git to use a custom diff driver called rails_credentials whenever it diffs those encrypted files. On its own, that line does nothing. Git still needs to know what rails_credentials actually means.
The second piece is a git config entry that Rails sets up for you:
git config --get diff.rails_credentials.textconv
# => bin/rails credentials:diff
The textconv setting tells git: before you diff this file, run it through this command first and diff the output instead. So git pipes the encrypted file through bin/rails credentials:diff, which decrypts it using your local master key, and then diffs the plaintext result.
Your secrets never leave your machine
This only works locally, on a machine that has the master key. The git history still contains the encrypted blob. If someone clones your repo without config/master.key, they see the raw ciphertext in diffs, which is exactly what you want.
The decryption happens on the fly, in memory, just for the diff. Nothing plaintext is written to disk or committed.
Why this matters
Without this, reviewing credential changes is painful. You edit the file, commit it, and the diff is a meaningless blob swap. You have no way to verify what actually changed without manually decrypting both versions and comparing them yourself.
With the textconv driver, git diff and git log -p both show you the real changes. You can see exactly which key was added, removed, or modified. Code review on credential changes becomes possible.
A small feature that changes how you work
I have been using Rails credentials for a while and never noticed this was happening. It is one of those features that works so quietly you do not realise it is there until you think about what should have happened. I expected base64 noise and got a clean diff instead, and it took me a moment to figure out why.
It is a good reminder to read your .gitattributes file. There might be more going on in there than you think.