Skip to content

Instantly share code, notes, and snippets.

@hvdijk
Created January 6, 2022 15:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hvdijk/1ff062c5c4565905de05ddd7a4257e32 to your computer and use it in GitHub Desktop.
Save hvdijk/1ff062c5c4565905de05ddd7a4257e32 to your computer and use it in GitHub Desktop.
gitx() {
local gitdir gitdirtx=false
local worktree worktreetx=false
gitdir=$(git rev-parse --git-dir) || return $?
worktree=$(git rev-parse --show-toplevel) || return $?
case $gitdir in *.git/worktrees/tx) gitdirtx=true;; esac
case $worktree in *.git/tx) worktreetx=true;; esac
case ${1-} in
begin)
test "$gitdirtx:$worktreetx" = "false:false" || {
echo "gitx: already in a transaction" >&2
return 1
}
git worktree add "${gitdir}/tx" --detach || return $?
cd "${gitdir}/tx" || return $?
gitdir=$(git rev-parse --git-dir) || return $?
printf "%s\n" "$OLDPWD" > "$gitdir/tx-source"
;;
commit)
test "$gitdirtx:$worktreetx" = "true:true" || {
echo "gitx: not in a transaction" >&2
return 1
}
{ git diff-files --quiet --ignore-submodules &&
git diff-index --quiet --cached --ignore-submodules HEAD; } || {
echo "gitx: worktree contains uncommitted changes" >&2
return 1
}
local hash branch
hash=$(git rev-parse HEAD) || return $?
worktree=$(cat -- "$gitdir/tx-source") || return $?
if branch=$(git -C "$worktree" symbolic-ref --quiet HEAD)
then
case $branch in
refs/heads/*) branch=${branch#refs/heads/} ;;
*) echo "cannot determine branch name" >&2
return 1 ;;
esac
else unset branch
fi
gitdir=$(git -C "$worktree" rev-parse --git-dir) || return $?
git -C "$worktree" checkout ${branch+-B "$branch"} $hash || return $?
cd -- "${worktree}" || return $?
git worktree remove "${gitdir}/tx" || return $?
;;
rollback)
test "$gitdirtx:$worktreetx" = "true:true" || {
echo "gitx: not in a transaction" >&2
return 1
}
worktree=$(cat -- "$gitdir/tx-source") || return $?
gitdir=$(git -C "$worktree" rev-parse --git-dir) || return $?
cd -- "${worktree}" || return $?
git worktree remove -f "${gitdir}/tx" || return $?
;;
*)
echo "usage: gitx begin|commit|rollback" >&2
return 1
;;
esac
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment