Something went wrong. Try again.
Dotfiles for my macos setup
Something went wrong. Try again.
3.0 kB · 101 lines
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102#!/usr/bin/env bash
set -Eeuo pipefail
script_name="git wt"
usage() { cat <<EOFUsage: $script_name <branch>
Creates a worktree for <branch> under <gj.root>/worktree/<owner>/<repo>/<branch>and prints its path. Creates the branch if it does not exist.If <branch> is already checked out in a worktree, prints that path. If it ischecked out in the main repository, that checkout is switched to the defaultbranch (or detached) first, so the branch can move to its own worktree.
Config: gj.root Directory where repositories are stored.
Example: cd ($script_name pb/my-feature)EOF}
# Prints the path of the worktree that has <branch> checked out, if any.worktree_for_branch() { git worktree list --porcelain | awk -v ref="branch refs/heads/$1" ' /^worktree / { path = substr($0, 10) } $0 == ref { print path; exit }'}
# Frees <branch> from the worktree at <path> so it can be checked out elsewhere.release_branch() { local branch=$1 path=$2 default [[ -z "$(git -C "$path" status --porcelain)" ]] || die "$branch is checked out in $path with uncommitted changes; commit or stash first" default=$(git -C "$path" default-branch 2>/dev/null || true) if [[ -n "$default" && "$default" != "$branch" ]] && git -C "$path" switch --quiet "$default" 2>/dev/null; then printf 'Switched %s to %s\n' "$path" "$default" >&2 else git -C "$path" switch --quiet --detach printf 'Detached HEAD in %s\n' "$path" >&2 fi}
die() { printf '%s\n' "$*" >&2 exit 1}
main() { [[ $# -eq 1 ]] || { usage exit 2 } case "$1" in -h | --help) usage exit 0 ;; esac
local branch=$1 root toplevel common main dest existing
root=$(git config --global --get gj.root || true) [[ -n "$root" ]] || die "gj.root is not set in git config" root="${root/#\~/$HOME}"
toplevel=$(git rev-parse --show-toplevel 2>/dev/null) || die "Not inside a git repository" [[ "$toplevel" == "$root"/* ]] || die "Repository is not under gj.root: $toplevel"
# Use the main repository path even when run from inside a linked worktree. common=$(git rev-parse --path-format=absolute --git-common-dir) main=${common%/.git} if [[ "$toplevel" == "$root"/worktree/* ]]; then toplevel=$main fi
dest="$root/worktree/${toplevel#"$root"/}/${branch//\//-}"
existing=$(worktree_for_branch "$branch") if [[ -n "$existing" && "$existing" != "$main" ]]; then printf '%s\n' "$existing" return fi [[ -z "$existing" ]] || release_branch "$branch" "$existing"
if [[ ! -d "$dest" ]]; then git fetch --prune --quiet if git show-ref --verify --quiet "refs/heads/$branch" || git show-ref --verify --quiet "refs/remotes/origin/$branch"; then git worktree add --quiet "$dest" "$branch" else git worktree add --quiet -b "$branch" "$dest" fi fi
printf '%s\n' "$dest"}
main "$@"