When the git-worktree call exits with an error we can delete the temporary directory as nothing is in it.
63 lines
1.9 KiB
Bash
Executable File
63 lines
1.9 KiB
Bash
Executable File
#!/usr/bin/env zsh
|
|
|
|
# Create a temporary worktree.
|
|
#
|
|
# Useful for doing quick tasks on other branches without modifying the current
|
|
# working tree. So no broken/outdated symlinks to dotfiles or unnecessary
|
|
# recompiling after switching back for example.
|
|
#
|
|
# Checks out the first argument in a worktree at a temporary directory. Then
|
|
# spawns an interactive shell inside of it.
|
|
#
|
|
# When the shell closes the worktree is tried to be removed. Until that works
|
|
# without problems (e.g. dirty), a new shell is spawned to resolve all conflicts
|
|
# (e.g. stashing).
|
|
#
|
|
# Instead of dropping in an interactive shell, the commands to execute can be
|
|
# passed via stdin. If any conflicts arise, all further shells are interactive.
|
|
# TODO: Override with flag that just `stash -u`
|
|
#
|
|
# Examples for scripted usage:
|
|
# Merge branches without leaving the current one:
|
|
# % git-checkout-worktree main <<<"git merge dev"
|
|
#
|
|
# Same for rebase (as `git rebase dev feature` switches to `feature`):
|
|
# % git-checkout-worktree feature <<<"git rebase dev"
|
|
|
|
emulate -L zsh -o err_return -o no_unset
|
|
|
|
local REPO_NAME WORKTREE_PATH
|
|
REPO_NAME="${$(git rev-parse --show-toplevel):t}"
|
|
WORKTREE_PATH="$(mktemp -d -p "" "worktree.XXX.$REPO_NAME.${1//\//_}")"
|
|
|
|
git worktree add "$WORKTREE_PATH" "$@" || ret=$?
|
|
|
|
if (( ret )); then
|
|
rmdir "$WORKTREE_PATH"
|
|
return $ret
|
|
fi
|
|
|
|
trap '
|
|
errc=$?
|
|
<&2 printf "Exiting abnormally. Check and possibly remove '$WORKTREE_PATH' manually.\n"
|
|
return $errc
|
|
' INT QUIT TERM EXIT
|
|
|
|
pushd -q "$WORKTREE_PATH"
|
|
|
|
"$SHELL" && errc=$? || errc=$?
|
|
|
|
# Restart the shell (forcefully interactive) until the worktree is removed
|
|
until [[ ! -e "$WORKTREE_PATH" ]] || git worktree remove "$WORKTREE_PATH"; do
|
|
[[ -t 0 ]] ||
|
|
>&2 printf "Dropping into interactive shell to resolve conflicts\n"
|
|
"$SHELL" -i && errc=$? || errc=$?
|
|
done
|
|
|
|
# Reset traps and PWD
|
|
trap '-' INT QUIT TERM EXIT
|
|
popd -q || true
|
|
|
|
git worktree prune
|
|
return $errc
|