Skip to content

Instantly share code, notes, and snippets.

@LarryRuane
Last active August 1, 2019 16:36
Show Gist options
  • Save LarryRuane/1ddfb7e9e0a44f5ed64a55278a698d46 to your computer and use it in GitHub Desktop.
Save LarryRuane/1ddfb7e9e0a44f5ed64a55278a698d46 to your computer and use it in GitHub Desktop.
Better ACK - squash interaction using git tree hash
#!/bin/bash
#
# This script demonstrates how to use the git tree hash to allow squashing
# after ACKs without invalidating the ACK.
#
# ACKs in PRs often mention the commit hash being approved, but if the developer
# then squashes before the merge, this changes the commit hash (the post-squash
# commit hash doesn't match the latest pre-squash commit hash). This is because
# the commit hash depends on things that squashing changes.
#
# How can the reviewers be sure that no changes occurred as part of the squash,
# without carefully re-reviewing the entire PR (as one large commit)? This concern
# does not require that the PR submitter be considered potentially malicious;
# a change may occur unintentionally.
#
# A commit's tree hash, in contrast, depends only on the contents of the files
# (and also their metadata, such as permissions and directory layout). Squashing
# does not change the tree hash. I'd like to encourage reviewers to ACK the tree
# hash, instead of the commit hash. And then whoever is initiating the merge should
# verify that the post-squash tree hash matches the pre-squash tree hash.
#
# The tree hash can be obtained using git log. But often reviewers look at the
# PR only on the github website, without making a clone. Unfortunately, github
# currently doesn't show a commit's tree hash, only its commit hash. However,
# you can access github's API using a curl command (shown below) to obtain the
# tree hash without needing to clone the PR's branch.
#
# This self-contained script demonstrates that squashing doesn't change the tree
# hash. (It doesn't demonstrate that changing file contents does change the tree
# hash; that's left as an exercise for the reader.) Just run it and inspect its
# output. It leaves behind a repo, ack-tree-hash-demo/, that you can just remove.
# This script does not modify github in any way.
#
set -x
git init ack-tree-hash-demo
cd ack-tree-hash-demo
: before the PR begins, we have a baseline
echo hello world base > myfile
git add myfile
git commit -m 'myfile base'
: start working on the PR
echo hello world fix-v1 > myfile
git add myfile
git commit -m 'myfile fix-v1'
: review turned up a problem
echo hello world fix-v2 > myfile
git add myfile
git commit -m 'myfile fix-v2'
: version 2 is good, reviewer ACKs mention tree hash:
git log -n1 --pretty='%T'
: before merging, squash out fix-v1
: pop off the last two commits, or can use git rebase -i
git reset HEAD~2
git add myfile
git commit -m 'myfile version final'
: squashed, but commit hash has changed
: did the file change since the ACK? we can check
: before doing r+, the review can verify same tree hash
: previous tree hash was 4810b76f4c22430ccfb38d177fa691fc3475c818
git log -n1 --pretty='%T'
: unfortunately, tree hash is not on the github website,
: to get the tree hash from a commit hash without a clone:
curl -s https://api.github.com/repos/zcash/zcash/commits/c68511b8760f2f699984c2e6db710957848f8e56 | jq .commit.tree.sha
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment