Skip to content

Instantly share code, notes, and snippets.

@oconnor663
Created October 4, 2017 17:02
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save oconnor663/8ef94b337a1614e40969f7a3ff2bffba to your computer and use it in GitHub Desktop.
Save oconnor663/8ef94b337a1614e40969f7a3ff2bffba to your computer and use it in GitHub Desktop.
edit a git commit without changing the hash
#! /bin/bash
d="$(mktemp -d)"
# Make a git repo with one file in it.
mkdir "$d/good"
cd "$d/good"
git init
echo good > file.txt
git add -A
git commit -m "first commit"
# Copy the whole thing.
cp -r "$d/good" "$d/bad"
# Go in the copy and edit the object that holds file.txt. Its path is always
# the same because, unlike the commit object, it doesn't contain any
# timestamps.
# NOTE: The blob object contains its own length, so if we wanted to substitute
# something other than another 4 bytes in there, we'd need to edit the length
# too.
file_hash_path=".git/objects/12/799ccbe7ce445b11b7bd4833bcc2c2ce1b48b7"
chmod +w "$d/bad/$file_hash_path"
cat "$d/good/$file_hash_path" \
| python2 -c "import zlib, sys; sys.stdout.write(zlib.decompress(sys.stdin.read()))" \
| sed 's/good/💩/' \
| python2 -c "import zlib, sys; sys.stdout.write(zlib.compress(sys.stdin.read()))" \
> "$d/bad/$file_hash_path"
echo "Here's a commit from the good repo:"
echo
git -C "$d/good" show -p
echo
echo "And here's "the same commit" from the bad repo:"
echo
git -C "$d/bad" show -p
@y-nk
Copy link

y-nk commented May 22, 2019

@oconnor663 thanks for clarification :)

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