From 5eac80f582938453458d332c594a06eb98a90449 Mon Sep 17 00:00:00 2001 From: Michael Bianco Date: Wed, 26 Nov 2025 06:22:40 -0700 Subject: [PATCH 1/3] feat: exclude worktree branches Switching to a branch occupied by another worktree results in an error. Until proper support for work trees is released, I think this is a good stop gap. --- bin/git-forgit | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/bin/git-forgit b/bin/git-forgit index 3ae4e516..1663d09a 100755 --- a/bin/git-forgit +++ b/bin/git-forgit @@ -65,6 +65,14 @@ _forgit_emojify() { fi } +_forgit_worktree_filter() { + if [[ "${FORGIT_CHECKOUT_BRANCH_EXCLUDE_WORKTREES:-true}" == "true" ]]; then + grep -v '^[+]' + else + cat + fi +} + # extract the first git sha occurring in the input and strip trailing newline _forgit_extract_sha() { grep -Eo '[a-f0-9]+' | head -1 | tr -d '[:space:]' @@ -879,7 +887,7 @@ _forgit_checkout_branch() { " _forgit_checkout_branch_branch_git_opts=() _forgit_parse_array _forgit_checkout_branch_branch_git_opts "$FORGIT_CHECKOUT_BRANCH_BRANCH_GIT_OPTS" - branch="$(git branch --color=always "${_forgit_checkout_branch_branch_git_opts[@]:---all}" | LC_ALL=C sort -k1.1,1.1 -rs | + branch="$(git branch --color=always "${_forgit_checkout_branch_branch_git_opts[@]:---all}" | _forgit_worktree_filter | LC_ALL=C sort -k1.1,1.1 -rs | FZF_DEFAULT_OPTS="$opts" fzf | awk '{print $1}')" [[ -z "$branch" ]] && return 1 From 1350f046970aa090fdd4578fde486dea25dc0276 Mon Sep 17 00:00:00 2001 From: Michael Bianco Date: Wed, 26 Nov 2025 08:37:57 -0700 Subject: [PATCH 2/3] docs: worktree exclusion --- README.md | 7 ++++--- bin/git-forgit | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6db49409..b882d4f6 100644 --- a/README.md +++ b/README.md @@ -384,9 +384,10 @@ export FORGIT_LOG_FZF_OPTS=' ## other options -| Option | Description | Default | -|-----------------------------|-------------------------------------------|-----------------------------------------------| -| `FORGIT_LOG_FORMAT` | git log format | `%C(auto)%h%d %s %C(black)%C(bold)%cr%Creset` | +| Option | Description | Default | +|--------------------------------------------|-----------------------------------------------|-----------------------------------------------| +| `FORGIT_CHECKOUT_BRANCH_EXCLUDE_WORKTREES` | exclude worktree branches in `gcb` | `true` | +| `FORGIT_LOG_FORMAT` | git log format | `%C(auto)%h%d %s %C(black)%C(bold)%cr%Creset` | | `FORGIT_PREVIEW_CONTEXT` | lines of diff context in preview mode | 3 | | `FORGIT_FULLSCREEN_CONTEXT` | lines of diff context in full-screen mode | 10 | | `FORGIT_DIR_VIEW` | command used to preview directories | `tree` if available, otherwise `find` | diff --git a/bin/git-forgit b/bin/git-forgit index 1663d09a..e2c5b42c 100755 --- a/bin/git-forgit +++ b/bin/git-forgit @@ -67,6 +67,7 @@ _forgit_emojify() { _forgit_worktree_filter() { if [[ "${FORGIT_CHECKOUT_BRANCH_EXCLUDE_WORKTREES:-true}" == "true" ]]; then + # Worktree branches are prefixed with '+' in 'git branch' output grep -v '^[+]' else cat From b320efaa2ab4e6823872fdab973dacf8e51db9ae Mon Sep 17 00:00:00 2001 From: Michael Bianco Date: Wed, 26 Nov 2025 08:38:10 -0700 Subject: [PATCH 3/3] test: worktree exclusion tests --- tests/worktree_exclude.test.sh | 46 ++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 tests/worktree_exclude.test.sh diff --git a/tests/worktree_exclude.test.sh b/tests/worktree_exclude.test.sh new file mode 100644 index 00000000..ef6f5821 --- /dev/null +++ b/tests/worktree_exclude.test.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash + +function set_up() { + source bin/git-forgit +} + +function test_forgit_worktree_filter_excludes_plus_lines_by_default() { + local input="+ worktree-branch +* main-branch + other-branch" + + # Default behavior (true) + local actual + actual=$(echo "$input" | _forgit_worktree_filter) + local expected="* main-branch + other-branch" + + assert_same "$expected" "$actual" +} + +function test_forgit_worktree_filter_excludes_plus_lines_when_explicitly_enabled() { + export FORGIT_CHECKOUT_BRANCH_EXCLUDE_WORKTREES="true" + local input="+ worktree-branch +* main-branch" + + local actual + actual=$(echo "$input" | _forgit_worktree_filter) + local expected="* main-branch" + + assert_same "$expected" "$actual" + unset FORGIT_CHECKOUT_BRANCH_EXCLUDE_WORKTREES +} + +function test_forgit_worktree_filter_includes_plus_lines_when_disabled() { + export FORGIT_CHECKOUT_BRANCH_EXCLUDE_WORKTREES="false" + local input="+ worktree-branch +* main-branch" + + local actual + actual=$(echo "$input" | _forgit_worktree_filter) + local expected="+ worktree-branch +* main-branch" + + assert_same "$expected" "$actual" + unset FORGIT_CHECKOUT_BRANCH_EXCLUDE_WORKTREES +}