From 524c2ef8a9527afe3e612660820c17fe461ce086 Mon Sep 17 00:00:00 2001 From: Semisol Date: Tue, 17 Aug 2021 12:43:30 +0300 Subject: [PATCH] Add the script and reword README --- README.md | 2 +- git-force | 131 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+), 1 deletion(-) create mode 100755 git-force diff --git a/README.md b/README.md index be1247f..e12570c 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ # git-force -small utility to explain a force push before pushing, to help prevent accidents with git fetch and --force-with-lease \ No newline at end of file +A small utility to display what commits will be dropped and which will be added, and attempts to prevent overwrites with `--force-with-lease` from programs that repeadetly `git fetch`, and double checks remote and local to error out if any changed after confirming. \ No newline at end of file diff --git a/git-force b/git-force new file mode 100755 index 0000000..6d7cbf6 --- /dev/null +++ b/git-force @@ -0,0 +1,131 @@ +#!/bin/bash +if [[ "$1" == "--help" || "$1" == "-h" ]] +then + echo "Usage:" + echo " git force" + echo " git force " + echo " git force " + exit 0 +fi +REMOTE="" +BRANCH="" +PRETTY="--pretty=format:%h, %an <%ae>, %ar: %s" +if [[ "$#" == "0" ]] +then + BRANCH="$(git branch --show-current)" + if [[ "$BRANCH" == "" ]] + then + echo "error: currently in detached HEAD state" >&2 + exit 1 + fi +fi +if [[ "$#" -gt "0" ]] +then + REMOTE="$1" + git config "remote.$REMOTE.url" > /dev/null 2>&1 + if [[ "$?" != "0" ]] + then + echo "error: specified remote is invalid" >&2 + exit 2 + fi +fi +if [[ "$#" -gt "1" ]] +then + BRANCH="$2" + git rev-parse --verify "$BRANCH" > /dev/null 2>&1 + if [[ "$?" != "0" ]] + then + echo "error: specified branch is invalid" >&2 + exit 3 + fi +fi +if [[ "$REMOTE" == "" ]] +then + REMOTE=$(git config "branch.$BRANCH.remote") + if [[ "$?" != "0" ]] + then + echo "error: current branch does not have a remote and no remote was specified" >&2 + echo "see: git force --help" + exit 4 + fi +fi +if [[ "$REMOTE" == "" || "$BRANCH" == "" ]] +then + echo "assertion failed: remote or branch is blank" >&2 + exit 5 +fi +REMOTE_BRANCH="$REMOTE/$BRANCH" +REMOTE_HASH="$(git rev-parse "$REMOTE_BRANCH")" # later used to throw errors if something changes remote or local +if [[ "$?" != "0" || "$REMOTE_HASH" == "" ]] +then + echo "internal error: failed to fetch remote hash" >&2 + exit 5 +fi +LOCAL_HASH="$(git rev-parse "$BRANCH")" # as that may cause the user unintentionally pushing/overwriting unwanted things +if [[ "$?" != "0" || "$LOCAL_HASH" == "" ]] +then + echo "internal error: failed to fetch local hash" >&2 + exit 5 +fi + +if [[ "$REMOTE_HASH" == "$LOCAL_HASH" ]] +then + echo "error: the branches are already the same" >&2 + exit 8 +fi + +if [[ "$REMOTE_HASH" == "$FORK_POINT" ]] +then + echo "error: the branches have not diverged" >&2 + exit 9 +fi + +FORK_POINT="$(git merge-base "$BRANCH" "$REMOTE_BRANCH")" +if [[ "$?" != "0" ]] +then +echo "The branches do not have a common ancestor, the latest commits for each are listed below:" +echo "" +echo "remote:" +git show -s "$PRETTY" "$REMOTE_HASH" +echo "" +echo "remote:" +git show -s "$PRETTY" "$REMOTE_HASH" +else +echo "The following commits will be OVERWRITTEN:" +git log "$PRETTY" "$FORK_POINT..$REMOTE_HASH" +echo "" +echo "The following commits will overwrite the above commits:" +git log "$PRETTY" "$FORK_POINT..$LOCAL_HASH" +fi +echo "" +read -p "Continue? [y/N] " SHOULD_CONTINUE +if [[ "$SHOULD_CONTINUE" != "y" ]] +then +echo "Abort." >&2 +exit 6 +fi +REMOTE_HASH_2="$(git rev-parse "$REMOTE_BRANCH")" +LOCAL_HASH_2="$(git rev-parse "$BRANCH")" +if [[ "$REMOTE_HASH_2" != "$REMOTE_HASH" ]] +then +echo "@@@@@@@@@@@@@@@@@@@@@@@@@" >&2 +echo "@ REMOTE HAS UPDATED! @" >&2 +echo "@@@@@@@@@@@@@@@@@@@@@@@@@" >&2 +echo "" >&2 +echo "The remote updated from $REMOTE_HASH" +echo "to $REMOTE_HASH_2 while you were confirming." +echo "Please re-run this command and check again." +exit 7 +fi +if [[ "$LOCAL_HASH_2" != "$LOCAL_HASH" ]] +then +echo "@@@@@@@@@@@@@@@@@@@@@@@@" >&2 +echo "@ LOCAL HAS UPDATED! @" >&2 +echo "@@@@@@@@@@@@@@@@@@@@@@@@" >&2 +echo "" >&2 +echo "The local updated from $LOCAL_HASH" +echo "to $LOCAL_HASH_2 while you were confirming." +echo "Please re-run this command and check again." +exit 7 +fi +git push --force-with-lease "$REMOTE" "$BRANCH" \ No newline at end of file