wt-close.sh 3.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. #!/usr/bin/env bash
  2. #############################################################################
  3. # wt-close.sh — Remove a git worktree and optionally clean up its branch
  4. #
  5. # Usage: wt-close.sh <name> [--keep-branch]
  6. # name Short name used when creating (e.g. feature-auth)
  7. # --keep-branch Skip branch deletion (useful if branch is unmerged)
  8. #############################################################################
  9. set -euo pipefail
  10. # ── Locate main repo root ─────────────────────────────────────────────────
  11. find_git_root() {
  12. local dir
  13. dir="$(pwd)"
  14. while [ "$dir" != "/" ]; do
  15. if [ -d "$dir/.git" ]; then
  16. echo "$dir"
  17. return 0
  18. fi
  19. dir="$(dirname "$dir")"
  20. done
  21. echo "ERROR: not inside a git repository" >&2
  22. return 1
  23. }
  24. MAIN_REPO="$(find_git_root)"
  25. GITHUB_ROOT="$(dirname "$MAIN_REPO")"
  26. REPO_NAME="$(basename "$MAIN_REPO")"
  27. # ── Args ──────────────────────────────────────────────────────────────────
  28. NAME="${1:-}"
  29. KEEP_BRANCH=false
  30. if [[ -z "$NAME" ]]; then
  31. echo "Usage: wt-close.sh <name> [--keep-branch]"
  32. echo " e.g. wt-close.sh feature-auth"
  33. exit 1
  34. fi
  35. shift
  36. for arg in "$@"; do
  37. if [[ "$arg" == "--keep-branch" ]]; then
  38. KEEP_BRANCH=true
  39. fi
  40. done
  41. WORKTREE_DIR="$GITHUB_ROOT/${REPO_NAME}-${NAME}"
  42. if [[ ! -d "$WORKTREE_DIR" ]]; then
  43. echo "ERROR: worktree directory not found: $WORKTREE_DIR" >&2
  44. exit 1
  45. fi
  46. echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
  47. echo " Removing worktree: ${REPO_NAME}-${NAME}"
  48. echo " Path: $WORKTREE_DIR"
  49. echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
  50. # ── Stop Docker Compose if running ───────────────────────────────────────
  51. if [[ -f "$WORKTREE_DIR/docker-compose.yml" ]]; then
  52. echo "→ Stopping Docker Compose..."
  53. if [[ -f "$WORKTREE_DIR/.env" ]]; then
  54. docker compose --env-file "$WORKTREE_DIR/.env" -f "$WORKTREE_DIR/docker-compose.yml" down -v 2>/dev/null || true
  55. else
  56. docker compose -f "$WORKTREE_DIR/docker-compose.yml" down -v 2>/dev/null || true
  57. fi
  58. fi
  59. # ── Kill Zellij session if running ───────────────────────────────────────
  60. if command -v zellij &>/dev/null; then
  61. if zellij list-sessions 2>/dev/null | grep -q "^$NAME"; then
  62. echo "→ Deleting Zellij session: $NAME"
  63. zellij delete-session "$NAME" 2>/dev/null || true
  64. fi
  65. fi
  66. # ── Find the branch name for this worktree ───────────────────────────────
  67. BRANCH="$(git -C "$WORKTREE_DIR" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "")"
  68. # ── Remove the worktree ───────────────────────────────────────────────────
  69. echo "→ Removing worktree..."
  70. git -C "$MAIN_REPO" worktree remove "$WORKTREE_DIR" --force
  71. git -C "$MAIN_REPO" worktree prune
  72. # ── Optionally delete the branch ─────────────────────────────────────────
  73. if [[ "$KEEP_BRANCH" == false ]] && [[ -n "$BRANCH" ]] && [[ "$BRANCH" != "main" ]] && [[ "$BRANCH" != "master" ]]; then
  74. echo "→ Deleting branch: $BRANCH"
  75. git -C "$MAIN_REPO" branch -d "$BRANCH" 2>/dev/null \
  76. || echo " (branch not deleted — has unmerged commits. Use --keep-branch or delete manually)"
  77. fi
  78. echo ""
  79. echo "✓ Worktree '${REPO_NAME}-${NAME}' removed"