Skip to content

Instantly share code, notes, and snippets.

@JonDotsoy
Last active July 22, 2026 22:11
Show Gist options
  • Select an option

  • Save JonDotsoy/de6cd164e4d742d894d2dc04ffcfc0e5 to your computer and use it in GitHub Desktop.

Select an option

Save JonDotsoy/de6cd164e4d742d894d2dc04ffcfc0e5 to your computer and use it in GitHub Desktop.
wt - utilidad para gestionar git worktrees

wt

Utilidad de shell para gestionar git worktrees: listarlos, abrirlos en VS Code por hash/branch, crear uno a partir de un PR de GitHub, o crear una branch y worktree nuevos.

Instalación

Copia wt a un directorio en tu PATH (por ejemplo ~/.bin o /usr/local/bin) y dale permisos de ejecución:

chmod +x wt

Requiere git. Opcionalmente gh y jq para mostrar el PR asociado en wt list y para wt open-pr.

Uso

wt list                 Lista los worktrees del repo actual
wt open <query>         Abre en VS Code el worktree cuyo commit hash (prefijo)
                        o branch coincida con <query>. Si <query> es un número,
                        se trata como PR (equivale a "wt open-pr <query>")
wt open-pr <PR>         Busca el PR con gh, crea el worktree si no existe
                        (en $WORKTREES_ROOT/<repo>/<branch>) y lo abre en VS Code
wt new <name>           Crea una branch y worktree nuevos a partir de <name>
                        (en $WORKTREES_ROOT/<repo>/<name>) y lo abre en VS Code
wt help                 Muestra esta ayuda

Variables de entorno

  • WT_ROOT — Carpeta raíz para worktrees creados por open-pr y new (default: ~/worktrees)
  • WT_EDITOR — Comando para abrir el worktree en cada subcomando (default: code)

Ejemplos

wt list                     # Lista los worktrees del repo actual
wt open feature/login       # Abre el worktree de la branch feature/login
wt open-pr 482               # Crea (si falta) y abre el worktree del PR #482
wt new feature/checkout     # Crea la branch y worktree feature/checkout
#!/usr/bin/env bash
#
# wt - utilidad para gestionar git worktrees: permite listarlos, abrirlos
# en VS Code por hash/branch, crear uno a partir de un PR de GitHub, o
# crear una branch y worktree nuevos.
#
# Usage:
# wt list Lista los worktrees del repo actual
# wt open <query> Abre un worktree existente en VS Code
# wt open-pr <PR> Crea (si falta) y abre el worktree de un PR
# wt new <name> Crea una branch y worktree nuevos
# wt help Muestra la ayuda completa
#
# Examples:
# wt list Lista los worktrees del repo actual
# wt open feature/login Abre el worktree de la branch feature/login
# wt open 32 Query numérica: equivale a "wt open-pr 32"
# wt open-pr 482 Crea (si falta) y abre el worktree del PR #482
# wt new feature/checkout Crea la branch y worktree feature/checkout
#
set -euo pipefail
# CONFIGS
WORKTREES_ROOT="${WT_ROOT:-$HOME/worktrees}"
WT_EDITOR="${WT_EDITOR:-code}"
repo_name() {
basename "$(git rev-parse --show-toplevel)"
}
cmd_list() {
local prs=""
if command -v gh >/dev/null 2>&1 && command -v jq >/dev/null 2>&1; then
prs="$(gh pr list --state open --json number,headRefName 2>/dev/null || echo '[]')"
fi
local c_pr="" c_hash="" c_branch="" c_reset=""
if [[ -t 1 ]]; then
c_pr=$'\033[1;32m'
c_hash=$'\033[33m'
c_branch=$'\033[36m'
c_reset=$'\033[0m'
fi
git worktree list --porcelain | awk '
/^worktree / { path=$2; n++ }
/^HEAD / { hash=$2 }
/^branch / { branch=$2; sub("refs/heads/", "", branch) }
/^$/ {
if (path != "") print n "\t" hash "\t" branch
path=""; hash=""; branch=""
}
END {
if (path != "") print n "\t" hash "\t" branch
}
' | while IFS=$'\t' read -r idx hash branch; do
if [[ "$idx" == "1" || -z "$branch" ]]; then
continue
fi
local short="${hash:0:7}"
local pr=""
if [[ -n "$prs" ]]; then
pr="$(jq -r --arg b "$branch" '.[] | select(.headRefName == $b) | "#\(.number)"' <<<"$prs" 2>/dev/null)"
fi
if [[ -n "$pr" ]]; then
printf -- '- %s%s%s %s%s%s %s%s%s\n' "$c_pr" "$pr" "$c_reset" "$c_hash" "$short" "$c_reset" "$c_branch" "$branch" "$c_reset"
else
printf -- '- %s%s%s %s%s%s\n' "$c_hash" "$short" "$c_reset" "$c_branch" "$branch" "$c_reset"
fi
done
}
cmd_open() {
local query="$1"
local match
if [[ "$query" =~ ^[0-9]+$ ]]; then
cmd_open_pr "$query"
return
fi
match="$(git worktree list --porcelain | awk -v q="$query" '
/^worktree / { path=$2 }
/^HEAD / { hash=$2 }
/^branch / { branch=$2; sub("refs/heads/", "", branch) }
/^$/ {
if (path != "" && (index(hash, q) == 1 || branch == q)) { print path; exit }
path=""; hash=""; branch=""
}
END {
if (path != "" && (index(hash, q) == 1 || branch == q)) print path
}
')"
if [[ -z "$match" ]]; then
echo "wt: no worktree found matching '$query'" >&2
exit 1
fi
"$WT_EDITOR" "$match"
}
#
# Sección "Uso" (Usage) del texto de ayuda (cmd_help): documenta cada
# subcomando soportado por el script (list, open, open-pr, new, help)
# junto con sus argumentos y qué hace cada uno. Se imprime tal cual al
# llamar `wt help` o al invocar un comando desconocido.
#
cmd_help() {
cat <<'EOF'
wt - manejo de git worktrees
Uso:
wt list Lista los worktrees del repo actual
wt open <query> Abre en VS Code el worktree cuyo commit hash (prefijo)
o branch coincida con <query>. Si <query> es un número,
se trata como PR (equivale a "wt open-pr <query>")
wt open-pr <PR> Busca el PR con gh, crea el worktree si no existe
(en $WORKTREES_ROOT/<repo>/<branch>) y lo abre en VS Code
wt new <name> Crea una branch y worktree nuevos a partir de <name>
(en $WORKTREES_ROOT/<repo>/<name>) y lo abre en VS Code
wt help Muestra esta ayuda
Variables de entorno:
WT_ROOT Carpeta raíz para worktrees creados por open-pr
(default: ~/worktrees)
WT_EDITOR Comando para abrir el worktree en cada subcomando
(default: code)
EOF
}
cmd_open_pr() {
local pr="$1"
local branch repo target existing
branch="$(gh pr view "$pr" --json headRefName -q .headRefName)"
repo="$(repo_name)"
target="$WORKTREES_ROOT/$repo/${branch//\//-}"
existing="$(git worktree list --porcelain | awk -v b="refs/heads/$branch" '
/^worktree / { path=$2 }
/^branch / { if ($2 == b) print path }
')"
if [[ -z "$existing" ]]; then
git fetch origin "pull/$pr/head:$branch"
mkdir -p "$WORKTREES_ROOT/$repo"
git worktree add "$target" "$branch"
existing="$target"
fi
"$WT_EDITOR" "$existing"
}
cmd_new() {
local name="$1"
local repo target existing
if [[ -z "$name" ]]; then
echo "wt: se requiere un nombre para 'wt new <name>'" >&2
exit 1
fi
repo="$(repo_name)"
target="$WORKTREES_ROOT/$repo/${name//\//-}"
existing="$(git worktree list --porcelain | awk -v b="refs/heads/$name" '
/^worktree / { path=$2 }
/^branch / { if ($2 == b) print path }
')"
if [[ -n "$existing" ]]; then
echo "wt: ya existe un worktree para la branch '$name' en $existing" >&2
"$WT_EDITOR" "$existing"
return
fi
mkdir -p "$WORKTREES_ROOT/$repo"
git worktree add -b "$name" "$target"
"$WT_EDITOR" "$target"
}
case "${1:-help}" in
list) cmd_list ;;
open) shift; cmd_open "$1" ;;
open-pr) shift; cmd_open_pr "$1" ;;
new) shift; cmd_new "$1" ;;
help|-h|--help) cmd_help ;;
*) echo "wt: unknown command '$1'" >&2; cmd_help >&2; exit 1 ;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment