GitLab Issue Worktree Cleanup
Overview
Use this skill to execute the existing workflow migrated from gitlab/clean-worktree.md.
Follow the playbook below and adapt commands to the current repository context.
Playbook
GitLab Issue Worktree Cleanup
Cleanup a git worktree and tmux session for a completed GitLab issue in the parent directory.
Command Usage
Provide a GitLab issue URL or issue number: $ARGUMENTS
Workflow
- •
Check glab CLI installation
- •Verify glab is installed and authenticated
- •If not installed, provide installation instructions and stop
- •
Extract and validate issue
- •Parse issue number from URL or direct number input
- •Fetch issue details using
glab issue view - •Display issue title for confirmation
- •
Find existing branch
- •Fetch latest branches from remote using
git fetch --all --prune - •Search for existing branches with the issue number (e.g.,
feature/123,issue-123) - •If no branch found, warn user but continue cleanup
- •Fetch latest branches from remote using
- •
Kill tmux session
- •Find tmux session named
<issue-number>-developor<issue-number>-* - •Kill the session using
tmux kill-session - •Skip if tmux is not installed or session doesn't exist
- •Confirm session terminated
- •Find tmux session named
- •
Remove worktree
- •Find worktree using
git worktree listwith branch name - •Remove worktree using
git worktree remove <path> - •If removal fails (uncommitted changes), offer force removal option
- •Handle case where worktree doesn't exist
- •Find worktree using
- •
Delete git branch
- •Delete the local branch using
git branch -d <branch-name> - •Delete the remote branch using
git push origin --delete <branch-name> - •Skip if no branch was found in step 3
- •If local deletion fails (unmerged), offer force deletion option
- •Handle case where remote branch doesn't exist
- •Delete the local branch using
- •
Confirm cleanup
- •Display what was cleaned up (tmux session, worktree, branch)
- •Show remaining worktrees using
git worktree list - •Provide status of cleanup operation
Example Implementation
bash
# Step 1: Check glab installation
if ! command -v glab &> /dev/null; then
echo "Error: glab CLI is not installed"
echo ""
echo "Installation instructions:"
echo " macOS: brew install glab"
echo " Linux: See https://gitlab.com/gitlab-org/cli#installation"
echo " Windows: scoop install glab"
echo ""
echo "After installation, authenticate with: glab auth login"
exit 1
fi
# Check authentication
if ! glab auth status &> /dev/null; then
echo "Error: glab is not authenticated"
echo "Please run: glab auth login"
exit 1
fi
# Step 2: Extract issue number
ISSUE_INPUT="$ARGUMENTS"
# Handle different input formats
if [[ "$ISSUE_INPUT" =~ /-/issues/([0-9]+) ]]; then
# Full URL format
ISSUE_NUMBER="${BASH_REMATCH[1]}"
elif [[ "$ISSUE_INPUT" =~ ^#?([0-9]+)$ ]]; then
# Issue number format (#123 or 123)
ISSUE_NUMBER="${BASH_REMATCH[1]}"
else
echo "Error: Invalid issue format. Provide URL or issue number."
exit 1
fi
# Step 3: Fetch issue details
echo "Fetching issue #$ISSUE_NUMBER..."
ISSUE_TITLE=$(glab issue view "$ISSUE_NUMBER" --json title -q '.title')
if [ -z "$ISSUE_TITLE" ]; then
echo "Error: Could not fetch issue #$ISSUE_NUMBER"
exit 1
fi
echo "Issue: #$ISSUE_NUMBER - $ISSUE_TITLE"
echo ""
# Step 4: Find branch name
echo "Fetching latest branches from remote..."
git fetch --all --prune
# Search for existing branches related to this issue
EXISTING_BRANCHES=$(git branch -a | grep -E "(feature[/-]${ISSUE_NUMBER}[^0-9]|feature[/-]${ISSUE_NUMBER}$|issue[-_]${ISSUE_NUMBER}|${ISSUE_NUMBER}[-_])" | head -n 1 | sed 's/^[* ]*//' | sed 's/remotes\/origin\///')
if [ -n "$EXISTING_BRANCHES" ]; then
EXISTING_BRANCHES=$(echo "$EXISTING_BRANCHES" | xargs)
echo "Found branch: $EXISTING_BRANCHES"
BRANCH_NAME="$EXISTING_BRANCHES"
else
echo "Warning: No branch found for issue #$ISSUE_NUMBER"
echo "Attempting cleanup by issue number only..."
BRANCH_NAME=""
fi
# Step 5: Kill tmux session
SESSION_NAME="${ISSUE_NUMBER}-develop"
TMUX_CLEANED=false
if command -v tmux &> /dev/null; then
# Find sessions matching the issue number
MATCHING_SESSIONS=$(tmux ls 2>/dev/null | grep "^${ISSUE_NUMBER}-" | cut -d: -f1)
if [ -n "$MATCHING_SESSIONS" ]; then
echo "Found tmux session(s) to clean up:"
while IFS= read -r session; do
echo " - $session"
tmux kill-session -t "$session" 2>/dev/null
if [ $? -eq 0 ]; then
echo " ✓ Killed session: $session"
TMUX_CLEANED=true
else
echo " ✗ Failed to kill session: $session"
fi
done <<< "$MATCHING_SESSIONS"
else
echo "No tmux session found for issue #$ISSUE_NUMBER"
fi
else
echo "Skipping tmux cleanup (tmux not installed)"
fi
echo ""
# Step 6: Remove worktree
WORKTREE_CLEANED=false
if [ -n "$BRANCH_NAME" ]; then
# Find worktree by branch name
WORKTREE_PATH=$(git worktree list | grep "$BRANCH_NAME" | awk '{print $1}')
if [ -n "$WORKTREE_PATH" ]; then
echo "Found worktree: $WORKTREE_PATH"
echo "Removing worktree..."
git worktree remove "$WORKTREE_PATH" 2>/dev/null
if [ $? -eq 0 ]; then
echo "✓ Removed worktree: $WORKTREE_PATH"
WORKTREE_CLEANED=true
else
echo "✗ Failed to remove worktree (may have uncommitted changes)"
echo ""
echo "To force removal, run:"
echo " git worktree remove --force $WORKTREE_PATH"
echo ""
echo "Or manually remove:"
echo " rm -rf $WORKTREE_PATH"
echo " git worktree prune"
fi
else
echo "No worktree found for branch: $BRANCH_NAME"
# Try to find by path pattern
WORKTREE_DIR="../worktrees/$BRANCH_NAME"
if [ -d "$WORKTREE_DIR" ]; then
echo "Found directory at: $WORKTREE_DIR (not registered as worktree)"
echo "Removing directory..."
rm -rf "$WORKTREE_DIR"
git worktree prune
echo "✓ Cleaned up directory and pruned worktrees"
WORKTREE_CLEANED=true
fi
fi
else
# Try to find worktree by issue number in path
echo "Searching for worktrees with issue #$ISSUE_NUMBER..."
WORKTREE_PATHS=$(git worktree list | grep -E "worktrees/(feature/)?${ISSUE_NUMBER}[-_]" | awk '{print $1}')
if [ -n "$WORKTREE_PATHS" ]; then
while IFS= read -r path; do
echo "Found worktree: $path"
git worktree remove "$path" 2>/dev/null
if [ $? -eq 0 ]; then
echo "✓ Removed worktree: $path"
WORKTREE_CLEANED=true
else
echo "✗ Failed to remove worktree: $path"
fi
done <<< "$WORKTREE_PATHS"
else
echo "No worktree found for issue #$ISSUE_NUMBER"
fi
fi
echo ""
# Step 7: Delete git branch
BRANCH_CLEANED=false
if [ -n "$BRANCH_NAME" ]; then
echo "Deleting branch: $BRANCH_NAME"
# Delete local branch
if git branch --list "$BRANCH_NAME" | grep -q .; then
git branch -d "$BRANCH_NAME" 2>/dev/null
if [ $? -eq 0 ]; then
echo " ✓ Deleted local branch: $BRANCH_NAME"
BRANCH_CLEANED=true
else
echo " ✗ Failed to delete local branch (may have unmerged changes)"
echo ""
echo " To force delete, run:"
echo " git branch -D $BRANCH_NAME"
fi
else
echo " No local branch found: $BRANCH_NAME"
fi
# Delete remote branch
if git ls-remote --heads origin "$BRANCH_NAME" | grep -q .; then
git push origin --delete "$BRANCH_NAME" 2>/dev/null
if [ $? -eq 0 ]; then
echo " ✓ Deleted remote branch: origin/$BRANCH_NAME"
BRANCH_CLEANED=true
else
echo " ✗ Failed to delete remote branch: origin/$BRANCH_NAME"
fi
else
echo " No remote branch found: origin/$BRANCH_NAME"
fi
else
echo "Skipping branch deletion (no branch found)"
fi
echo ""
# Step 8: Summary
echo "════════════════════════════════════════"
echo "Cleanup Summary for Issue #$ISSUE_NUMBER"
echo "════════════════════════════════════════"
if [ "$TMUX_CLEANED" = true ] || [ "$WORKTREE_CLEANED" = true ] || [ "$BRANCH_CLEANED" = true ]; then
echo "✓ Cleanup completed successfully"
[ "$TMUX_CLEANED" = true ] && echo " - tmux session(s) killed"
[ "$WORKTREE_CLEANED" = true ] && echo " - worktree(s) removed"
[ "$BRANCH_CLEANED" = true ] && echo " - branch deleted"
else
echo "⚠ No cleanup performed"
echo " No tmux session, worktree, or branch found for issue #$ISSUE_NUMBER"
fi
echo ""
echo "Remaining worktrees:"
git worktree list
Manual Cleanup Commands
If you prefer to clean up manually or the automatic cleanup fails, use these commands:
Remove a specific worktree:
bash
git worktree remove ../worktrees/<branch-name>
Force remove worktree (with uncommitted changes):
bash
git worktree remove --force ../worktrees/<branch-name>
Kill the associated tmux session:
bash
tmux kill-session -t <issue-number>-develop
Delete local and remote branch:
bash
# Safe delete (fails if unmerged) git branch -d <branch-name> # Force delete (even if unmerged) git branch -D <branch-name> # Delete remote branch git push origin --delete <branch-name>
Remove worktree, branch, and tmux session:
bash
git worktree remove ../worktrees/<branch-name> git branch -d <branch-name> git push origin --delete <branch-name> tmux kill-session -t <issue-number>-develop
Clean up orphaned worktree directories:
bash
# Remove directory and prune worktree registry rm -rf ../worktrees/<branch-name> git worktree prune
Bulk cleanup for closed issues:
bash
# List all worktrees git worktree list # Remove specific worktrees git worktree remove <path> # List all tmux sessions tmux ls # Kill specific sessions tmux kill-session -t <session-name>
Notes
- •Safety: The cleanup process checks for uncommitted changes and will not force-remove worktrees by default
- •Verification: Always verify the issue number before cleanup to avoid removing the wrong worktree
- •Branch detection: The command searches for branches using multiple naming patterns (feature/N, issue-N, N-)
- •Branch safety: Local branch deletion uses
-d(safe delete) by default, which fails if the branch has unmerged changes - •Graceful failure: If tmux, worktree, or branch doesn't exist, the command will skip that step and continue
- •Manual intervention: If automatic cleanup fails due to uncommitted changes, use manual cleanup commands
- •Consistency: This command is designed to work with worktrees created by the
create-worktreecommand - •Multiple sessions: The command will find and clean up all tmux sessions matching the issue number pattern
Best Practices
- •Before cleanup: Ensure all changes are committed and pushed to remote
- •Verify completion: Check that the issue is truly complete before cleaning up
- •Review changes: Use
git statusin the worktree before cleanup - •Branch deletion: The cleanup now deletes both local and remote branches automatically
- •Batch cleanup: Periodically clean up old worktrees for completed issues to save disk space