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
@oconnor663
Copy link
Author

I don't think you'll be able to get away with that. Git is willing to interact with bad commit objects locally, but usually once you try to transfer them over the network protocol (i.e. push them to GitHub), they get rejected. (If they didn't, that would be a fairly massive oversight by the GitHub security team.)

@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