-
-
Save gianpaolof/347c83fcb51ae8c272d4e713e31225d3 to your computer and use it in GitHub Desktop.
Two scripts that can be used to detect evil merges in Git. See http://stackoverflow.com/questions/27683077
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# A shell script to provide a meaningful diff output for a merge commit that can be used to determine whether the merge was evil. | |
# The script should be run from outside the git repository, with two arguments: | |
# 1 - the directory of the git repository | |
# 2 - the SHA for the merge commit to inspect | |
# The script will output one file: | |
# - the merge redone fresh without any conflicts resolved, diff'ed to the actual merge | |
output_file="diff.txt" | |
if [ "$#" -ne 2 ] | |
then | |
echo "ERROR: This script must be run with exactly two arguments: the directory for the Git repo, and the SHA for the merge commit to inspect." >&2 | |
echo "Usage: $0 GIT_REPO_DIR MERGE_COMMIT_SHA" >&2 | |
exit 1 | |
fi | |
# Store the current HEAD so we can put the repository back into the original state when finished | |
if ! original_head=$(git -C $1 symbolic-ref --short -q HEAD) # get the branch name, if possible | |
then | |
original_head=$(git -C $1 rev-parse HEAD) # detached HEAD, get the commit SHA | |
fi | |
# Perform the merge again, without resolving conflicts. Then diff the result with the actual merge commit we're inspecting. | |
git -C $1 checkout $2~ &>/dev/null | |
git -C $1 -c merge.conflictstyle=diff3 merge --no-ff $2^2 --no-commit &>/dev/null | |
git -C $1 add $(git -C $1 status -s | cut -c 3-) &>/dev/null | |
git -C $1 commit --no-edit &>/dev/null | |
git -C $1 diff HEAD..$2 > $output_file | |
# Put the repository back in the original state | |
git -C $1 checkout $original_head &>/dev/null |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# A shell script to provide a meaningful diff output for a merge commit that can be used to determine whether the merge was evil. | |
# The script should be run from outside the git repository, with two arguments: | |
# 1 - the directory of the git repository | |
# 2 - the SHA for the merge commit to inspect | |
# The script will output two files: | |
# - the merge redone fresh with conflicts resolved using the first parent, diff'ed to the actual merge | |
# - the merge redone fresh with conflicts resolved using the second parent, diff'ed to the actual merge | |
output_fileA="diffA.txt" | |
output_fileB="diffB.txt" | |
if [ "$#" -ne 2 ] | |
then | |
echo "ERROR: This script must be run with exactly two arguments: the directory for the Git repo, and the SHA for the merge commit to inspect." >&2 | |
echo "Usage: $0 GIT_REPO_DIR MERGE_COMMIT_SHA" >&2 | |
exit 1 | |
fi | |
# Store the current HEAD so we can put the repository back into the original state when finished | |
if ! original_head=$(git -C $1 symbolic-ref --short -q HEAD) # get the branch name, if possible | |
then | |
original_head=$(git -C $1 rev-parse HEAD) # detached HEAD, get the commit SHA | |
fi | |
# Perform the merge again, resolving conflicts using the version from the first parent. | |
# Then diff the result with the actual merge commit we're inspecting. | |
git -C $1 checkout $2~ &>/dev/null | |
git -C $1 merge --no-ff --no-edit -s recursive -Xours $2^2 &>/dev/null | |
git -C $1 diff HEAD..$2 > $output_fileA | |
# Perform the merge again, resolving conflicts using the version from the second parent. | |
# Then diff the result with the actual merge commit we're inspecting. | |
git -C $1 checkout $2~ &>/dev/null | |
git -C $1 merge --no-ff --no-edit -s recursive -Xtheirs $2^2 &>/dev/null | |
git -C $1 diff HEAD..$2 > $output_fileB | |
# Put the repository back in the original state | |
git -C $1 checkout $original_head &>/dev/null |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment