Skip to content

Instantly share code, notes, and snippets.

@mhofman
Last active July 18, 2018 21:21
Show Gist options
  • Save mhofman/364543bdcb16b26b95512ab2ccf0a83d to your computer and use it in GitHub Desktop.
Save mhofman/364543bdcb16b26b95512ab2ccf0a83d to your computer and use it in GitHub Desktop.
Git update hook to deploy files of a pushed branch into a corresponding worktree if it exists. The id of the worktree should match the branch name (rename/move if necessary). See https://git-scm.com/docs/git-worktree
#!/bin/sh
# Exit if any unhandled command fails
set -e
# --- Command line
refname="$1"
oldrev="$2"
newrev="$3"
# --- Safety check
if [ -z "$GIT_DIR" ]; then
echo "Don't run this script from the command line." >&2
echo " (if you want, you could supply GIT_DIR then run" >&2
echo " $0 <ref> <oldrev> <newrev>)" >&2
exit 1
fi
if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
echo "usage: $0 <ref> <oldrev> <newrev>" >&2
exit 1
fi
# if $newrev is 0000...0000, it's a commit to delete a ref.
zero="0000000000000000000000000000000000000000"
branch=${refname#refs/heads/}
#echo "oldrev=${oldrev} newrev=${newrev} refname=${refname} branch=${branch}"
[ "$refname" = "refs/heads/${branch}" ] || exit 0
case "$branch" in
""|"__empty__")
echo "Invalid branch name '$branch'" >&2
exit 1
;;
esac
branch_git_dir="${GIT_DIR}/worktrees/${branch}"
unset GIT_DIR
if [ ! -d ${branch_git_dir} ]; then
echo "No worktree found for branch $branch. Skipping deploy."
exit 0
fi
target="$(dirname "$(cat $branch_git_dir/gitdir)")"
folder="$(basename "$target")"
if [ ! -d ${target} ]; then
echo "Worktree $target for branch $branch is unavailable. Abording." >&2
exit 1
fi
currev="$(git -C "$target" rev-parse HEAD 2>/dev/null)" || currev=$zero
if [ "$oldrev" != "$currev" ]; then
echo "Warning! The current checked out revision $currev differs from the expected revision $oldrev."
fi
echo "Deploying branch '$branch' to '$target'"
if [ "$currev" != "$zero" ]; then
oldstash="$(git -C "$target" rev-parse -q --verify refs/stash)" || oldstash=$zero
git -C "$target" stash save -q "In worktree $folder: On commit $currev: Local changes"
newstash="$(git -C "$target" rev-parse -q --verify refs/stash)" || newstash=$zero
[ "$oldstash" == "$newstash" ] || echo "Warning! Saved local changes to stash."
fi
untracked_files=$(git -C "$target" ls-files --other --directory --exclude-standard)
if [ -n "$untracked_files" ]; then
echo "Warning! Untracked files exist in folder $folder:"
echo "$untracked_files"
fi
if [ "$newrev" != "$zero" ]; then
echo "Checking out $newrev"
git -C "$target" checkout -q --detach $newrev
else
echo "Removing all files"
git -C "$target" checkout -q --orphan __empty__
git -C "$target" rm -rf --ignore-unmatch .
fi
echo "Success! Revision $newrev is now deployed to '$folder'"
# --- Finished
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment