diff --git a/home/common/programs/opencode/commands/merge.md b/home/common/programs/opencode/commands/merge.md index 449cbd2..105954e 100644 --- a/home/common/programs/opencode/commands/merge.md +++ b/home/common/programs/opencode/commands/merge.md @@ -1,23 +1,100 @@ --- -description: Merge a worktree branch back into the base branch +description: Merge worktree changes and clean up safely --- -Merge a branch from the worktree. -If you're currently working on a worktree, assume that's the one I'm referring to. -Start by committing any staged and unstaged changes. I may have made changes to the worktree manually. -Then merge back the new main branch, since I may have made changes to it. +# Merge Worktree and Cleanup -# Language specific: +Merge changes from the current worktree into a target branch and clean up the worktree. -## Rust +**Usage:** `/merge [target-branch]` -Ensure cargo check is happy. -Ensure clippy is happy. clean up any new warnings. +**Arguments:** +- `$1`: Target branch to merge into (default: auto-detect main/master) -## Typescript +## Process -Ensure tsc is happy. +### 1. Pre-flight Checks -# Finally +```bash +CURRENT_BRANCH=$(git branch --show-current) +WORKTREE_DIR=$(git rev-parse --git-common-dir) -Squash the commits into a single one, merge into the base branch, and delete the worktree. +if [[ ! "$WORKTREE_DIR" == *".git/worktrees"* ]]; then + echo "❌ Error: You're not in a worktree" + exit 1 +fi + +if ! git diff-index --quiet HEAD --; then + echo "❌ Error: You have uncommitted changes" + git status --short + exit 1 +fi +``` + +### 2. Determine Target Branch + +```bash +TARGET_BRANCH="${1:-}" +if [ -z "$TARGET_BRANCH" ]; then + if git show-ref --verify --quiet refs/heads/main; then + TARGET_BRANCH="main" + elif git show-ref --verify --quiet refs/heads/master; then + TARGET_BRANCH="master" + else + echo "❌ Error: Cannot auto-detect main branch" + exit 1 + fi +fi +``` + +### 3. Update Target Branch + +```bash +WORKTREE_PATH=$(pwd) +COMMON_DIR=$(git rev-parse --git-common-dir) +REPO_ROOT=$(echo "$COMMON_DIR" | sed 's/\.git.*//' | sed 's/\/$//') +if [ "$COMMON_DIR" = ".git" ]; then + REPO_ROOT=$(git rev-parse --show-toplevel) +fi + +cd "$REPO_ROOT" +git checkout "$TARGET_BRANCH" +git pull origin "$TARGET_BRANCH" +``` + +### 4. Merge + +```bash +git merge --no-ff "$CURRENT_BRANCH" -m "Merge branch '$CURRENT_BRANCH'" +``` + +If you prefer a squash merge, do this instead: + +```bash +git merge --squash "$CURRENT_BRANCH" +git commit -m "feat: " +``` + +### 5. Push and Clean Up + +```bash +git push origin "$TARGET_BRANCH" + +git worktree remove "$WORKTREE_PATH" --force || rm -rf "$WORKTREE_PATH" +git branch -d "$CURRENT_BRANCH" || git branch -D "$CURRENT_BRANCH" +``` + +### 6. Optional: Delete Remote Branch + +```bash +git push origin --delete "$CURRENT_BRANCH" +``` + +## Language-specific checks + +### Rust +- `cargo check` +- `cargo clippy` (clean up new warnings) + +### TypeScript +- `tsc` diff --git a/home/common/programs/opencode/commands/work.md b/home/common/programs/opencode/commands/work.md index 1e3ce80..3a12497 100644 --- a/home/common/programs/opencode/commands/work.md +++ b/home/common/programs/opencode/commands/work.md @@ -1,8 +1,91 @@ --- -description: Start a new feature in a git worktree +description: Start parallel work on a feature using git worktree --- -In a worktrees directory inside the git project's root, create a new worktree for the requested feature. -create the directory if it doesn't exist. -keep the branch name concise, and don't include "opencode" in its name. -do all the work for the feature in the new worktree. -run "kitty @ set-tab-title" to set the tab title of this kitty session to "/" + +# Start Worktree for Feature + +Initialize a new git worktree to work on a feature in parallel with your current work. + +**Usage:** `/work "feature description"` +**Manual:** `/work branch-name` + +**Arguments:** +- `$1`: Feature description (quoted) OR branch name (single word) + +## Requirements + +- Must run from the main repository (not inside an existing worktree) +- Git installed, repository clean or stashable +- Worktrees live in `worktrees/` inside the repo root + +## Process + +### 1. Pre-flight Checks + +```bash +# Ensure we're in a git repo +git rev-parse --git-dir > /dev/null + +# Ensure not already in a worktree +CURRENT_GIT_DIR=$(git rev-parse --git-common-dir) +if [[ "$CURRENT_GIT_DIR" == *".git/worktrees"* ]]; then + echo "❌ Error: already inside a worktree" + exit 1 +fi + +# Ensure clean (or stash) +if ! git diff-index --quiet HEAD --; then + echo "⚠️ Working tree has changes" + git status --short + echo "Stash before creating worktree" + git stash push -m "Auto-stash before worktree" +fi +``` + +### 2. Determine Base Branch + +```bash +if git show-ref --verify --quiet refs/heads/main; then + BASE_BRANCH="main" +elif git show-ref --verify --quiet refs/heads/master; then + BASE_BRANCH="master" +else + echo "❌ Error: Cannot auto-detect base branch" + exit 1 +fi +``` + +### 3. Determine Branch Name + +If `$1` contains spaces, treat it as a description and generate a concise branch name. + +Rules: +- Lowercase, hyphens, max 50 chars +- Prefer `feat/`, `fix/`, `refactor/`, `chore/` prefixes when obvious + +If `$1` is a single word, use it directly. + +**Do not include "opencode" in the branch name.** + +### 4. Create Worktree + +```bash +REPO_ROOT=$(git rev-parse --show-toplevel) +WORKTREES_DIR="$REPO_ROOT/worktrees" +mkdir -p "$WORKTREES_DIR" + +WORKTREE_PATH="$WORKTREES_DIR/$BRANCH_NAME" +git worktree add -b "$BRANCH_NAME" "$WORKTREE_PATH" "$BASE_BRANCH" +``` + +### 5. Next Steps + +```bash +cd "$WORKTREE_PATH" +git status +``` + +## Notes + +- Use `/worktree-compare` to review changes before merging. +- Use `/merge` when ready to integrate. diff --git a/home/common/programs/opencode/commands/worktree-compare.md b/home/common/programs/opencode/commands/worktree-compare.md new file mode 100644 index 0000000..f3be915 --- /dev/null +++ b/home/common/programs/opencode/commands/worktree-compare.md @@ -0,0 +1,78 @@ +--- +description: Compare worktree changes with target branch before merging +--- + +# Compare Worktree Changes + +Visualize changes in the current worktree compared to a target branch (usually main/master). + +**Usage:** `/worktree-compare [target-branch]` + +**Arguments:** +- `$1`: Target branch to compare against (default: auto-detect main/master) + +## Process + +### 1. Verify Context + +```bash +CURRENT_BRANCH=$(git branch --show-current) +WORKTREE_DIR=$(git rev-parse --git-common-dir) + +if [[ ! "$WORKTREE_DIR" == *".git/worktrees"* ]]; then + echo "❌ Error: You're not in a worktree" + exit 1 +fi +``` + +### 2. Determine Target Branch + +```bash +TARGET_BRANCH="${1:-}" +if [ -z "$TARGET_BRANCH" ]; then + if git show-ref --verify --quiet refs/heads/main; then + TARGET_BRANCH="main" + elif git show-ref --verify --quiet refs/heads/master; then + TARGET_BRANCH="master" + else + echo "❌ Error: Cannot auto-detect main branch" + exit 1 + fi +fi +``` + +### 3. Update Target Branch + +```bash +git fetch origin "$TARGET_BRANCH:$TARGET_BRANCH" 2>/dev/null || true +``` + +### 4. Summary + Diff + +```bash +git diff --shortstat "$TARGET_BRANCH..$CURRENT_BRANCH" +git diff --name-status "$TARGET_BRANCH..$CURRENT_BRANCH" +git log "$TARGET_BRANCH..$CURRENT_BRANCH" --oneline --decorate --graph + +# Detailed diff (delta if installed) +if command -v delta &> /dev/null; then + git diff "$TARGET_BRANCH..$CURRENT_BRANCH" | delta +else + git diff "$TARGET_BRANCH..$CURRENT_BRANCH" --color=always | less -R +fi +``` + +### 5. Conflict Detection + +```bash +COMMON_FILES=$(comm -12 \ + <(git diff --name-only "$TARGET_BRANCH..$CURRENT_BRANCH" | sort) \ + <(git diff --name-only "$CURRENT_BRANCH..$TARGET_BRANCH" | sort)) + +if [ -z "$COMMON_FILES" ]; then + echo "✅ No potential conflicts detected" +else + echo "⚠️ Potential conflicts in:" + echo "$COMMON_FILES" +fi +``` diff --git a/home/common/programs/opencode/commands/worktree-list.md b/home/common/programs/opencode/commands/worktree-list.md new file mode 100644 index 0000000..bd2431d --- /dev/null +++ b/home/common/programs/opencode/commands/worktree-list.md @@ -0,0 +1,74 @@ +--- +description: List, manage, and clean up git worktrees +--- + +# List and Manage Worktrees + +**Usage:** +- `/worktree-list` - List all worktrees +- `/worktree-list cleanup` - Remove merged worktrees +- `/worktree-list prune` - Clean stale references + +## List All Worktrees + +```bash +if [ -z "$1" ]; then + git worktree list + exit 0 +fi +``` + +## Cleanup Merged Worktrees + +```bash +if [ "$1" = "cleanup" ]; then + if git show-ref --verify --quiet refs/heads/main; then + MAIN_BRANCH="main" + elif git show-ref --verify --quiet refs/heads/master; then + MAIN_BRANCH="master" + else + echo "❌ Error: Cannot find main/master" + exit 1 + fi + + MERGED_BRANCHES=$(git branch --merged "$MAIN_BRANCH" | grep -v '^\*' | grep -v "$MAIN_BRANCH") + if [ -z "$MERGED_BRANCHES" ]; then + echo "✅ No merged branches found" + exit 0 + fi + + while IFS= read -r branch; do + branch=$(echo "$branch" | xargs) + [ -z "$branch" ] && continue + + WORKTREE_PATH=$(git worktree list | grep "\[$branch\]" | awk '{print $1}') + if [ -n "$WORKTREE_PATH" ]; then + git worktree remove "$WORKTREE_PATH" --force 2>/dev/null || rm -rf "$WORKTREE_PATH" + fi + + git branch -d "$branch" 2>/dev/null || git branch -D "$branch" + done <<< "$MERGED_BRANCHES" + + git worktree prune + git worktree list + exit 0 +fi +``` + +## Prune Stale References + +```bash +if [ "$1" = "prune" ]; then + git worktree prune -v + git worktree list + exit 0 +fi +``` + +## Invalid Argument + +```bash +echo "❌ Error: Invalid argument '$1'" +echo "Usage: /worktree-list [cleanup|prune]" +exit 1 +``` diff --git a/home/common/programs/opencode/default.nix b/home/common/programs/opencode/default.nix index 111692f..b994891 100644 --- a/home/common/programs/opencode/default.nix +++ b/home/common/programs/opencode/default.nix @@ -29,6 +29,8 @@ xdg.configFile."opencode/commands/security-scan.md".source = ./commands/security-scan.md; xdg.configFile."opencode/commands/issue.md".source = ./commands/issue.md; xdg.configFile."opencode/commands/remove-deadcode.md".source = ./commands/remove-deadcode.md; + xdg.configFile."opencode/commands/worktree-compare.md".source = ./commands/worktree-compare.md; + xdg.configFile."opencode/commands/worktree-list.md".source = ./commands/worktree-list.md; # Skills xdg.configFile."opencode/skills/git-master/SKILL.md".source = ./skills/git-master/SKILL.md;