Skip to content

Instantly share code, notes, and snippets.

@marcopaganini
Last active October 17, 2023 16:46
Show Gist options
  • Save marcopaganini/62fc51a679f8985c10c3ca5d0c84031c to your computer and use it in GitHub Desktop.
Save marcopaganini/62fc51a679f8985c10c3ca5d0c84031c to your computer and use it in GitHub Desktop.
How to remove git-crypt from your repo (maintaining history).

How to remove git-crypt and maintain your history

I've been successfully using git-crypt to provide provide partial encryption to some of my repos. It's a great program and I'd definitely recommend it for your git repository encryption needs.

However, while installation is quite simple, I couldn't find good instructions on how to uninstall git-crypt and maintain history intact.

This guide provides simple instructions on how to accomplish that. In the end, you should have a new, unencrypted repository that is a copy of your original encrypted one, including all the commit history.

Some assumptions:

  • Your original (encrypted) repository has been cloned into /tmp/original.
  • Your new (clear text) repository will be under /tmp/new.
  • We'll use /tmp/patch for our temporary patch location.
  • Your original repository working directory is clean (git status should return nothing.)
  • You have rsync installed.

Note: I've tried this procedure on repositories with a linear commit line (no merge commits.)

Background

We'll use git format-patch with the --textconv command-line flag to create plain-text patches of the encrypted repo, and then use git am to apply these patches into a clean repo.

Preparing the environment

Remove any old directories and create the new ones. Initialize a clean git repository under /tmp/new:

rm -rf /tmp/{new,original,patch}
mkdir /tmp/{new,patch}
git init /tmp/new

Now clone your original (encrypted) repository under /tmp/original and use git-crypt unlock to unlock the working copy:

git clone YOUR_REPO_URL /tmp/original
cd /tmp/original
git-crypt unlock
<provide any needed credentials>

Create the patches

Create a patch for every single commit in the original repo:

cd /tmp/original
git format-patch --textconv --root HEAD -o /tmp/patch
<watch patch files to be written...>

Use ls -l /tmp/patch and confirm that a number of patch files were created under/tmp/patch.

Apply the patches on the new repo

We'll now apply the patches into the newly created repository (under /tmp/new).

cd /tmp/new
for i in /tmp/patch/*.patch; do git am "$i"; done

I've seen some warning messages, but they seem to be mostly harmless. Make sure this command iterates through all patches and does not encounter any fatal errors.

Once the patches have been applied, remove the git-crypt configuration from the new repository and submit the changes.

git rm .gitattributes
git rm -r .git-crypt
git commit -m 'Removed git-crypt. Thanks for all the fish!'

Note: If you have non-git-crypt stuff in .gitattributes, you'll have to edit the file and remove those lines only. Otherwise, it should be OK to remove the file completely.

Investigate differences

For some reason, even after a successful run of git am, my repo ended up with a few differences. Those were minor and I believe they were caused by different starting points in the repo history (the original repo started from an existing file, while the new one started from a blank slate).

We'll now copy every file under git control from the encrypted (but unlocked) working directory to the newly created (unencrypted) repository. This should make it easy to see any differences with git status and git diff:

cd /tmp/original
rsync -avp --files-from=<(git ls-files | grep -v '^.gitattributes\|git-crypt/') . /tmp/new
cd /tmp/new
git status

Use git diff to investigate any differences reported by git status. Add and commit any changes you see.

At this point we'll have a clean repository under /tmp/new that can be pushed to another location. Please note that the newly created repository has no remotes or special configs from the original.

Cleanup

Once everything is finished (and you saved /tmp/new into some other place) clean the temporary directories with:

rm -rf /tmp/{new,original,patch}

Hope this helps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment