Skip to content

Commit 1eefcb5

Browse files
committed
feat: add --folder flag for custom worktree folder names
Allow specifying a custom folder name with --folder when creating worktrees, decoupling the folder name from the branch name. Useful for long branch names that would create unwieldy folder names. Closes #81
1 parent 7a315d7 commit 1eefcb5

File tree

6 files changed

+44
-12
lines changed

6 files changed

+44
-12
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ git gtr new my-feature # Creates folder: my-feature
159159
git gtr new hotfix --from v1.2.3 # Create from specific ref
160160
git gtr new variant-1 --from-current # Create from current branch
161161
git gtr new feature/auth # Creates folder: feature-auth
162+
git gtr new feature/implement-user-authentication-with-oauth2-integration --folder auth # Custom folder name
162163
git gtr new feature-auth --name backend --force # Same branch, custom name
163164
git gtr new my-feature --name descriptive-variant # Optional: custom name without --force
164165
```
@@ -170,8 +171,9 @@ git gtr new my-feature --name descriptive-variant # Optional: custom name with
170171
- `--track <mode>`: Tracking mode (auto|remote|local|none)
171172
- `--no-copy`: Skip file copying
172173
- `--no-fetch`: Skip git fetch
173-
- `--force`: Allow same branch in multiple worktrees (**requires --name**)
174+
- `--force`: Allow same branch in multiple worktrees (**requires --name or --folder**)
174175
- `--name <suffix>`: Custom folder name suffix (optional, required with --force)
176+
- `--folder <name>`: Custom folder name (replaces default, useful for long branch names)
175177
- `--editor`, `-e`: Open in editor after creation
176178
- `--ai`, `-a`: Start AI tool after creation
177179
- `--yes`: Non-interactive mode

bin/gtr

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ cmd_create() {
130130
local yes_mode=0
131131
local force=0
132132
local custom_name=""
133+
local folder_override=""
133134
local open_editor=0
134135
local start_ai=0
135136

@@ -168,6 +169,10 @@ cmd_create() {
168169
custom_name="$2"
169170
shift 2
170171
;;
172+
--folder)
173+
folder_override="$2"
174+
shift 2
175+
;;
171176
--editor|-e)
172177
open_editor=1
173178
shift
@@ -191,12 +196,19 @@ cmd_create() {
191196
done
192197

193198
# Validate flag combinations
194-
if [ "$force" -eq 1 ] && [ -z "$custom_name" ]; then
195-
log_error "--force requires --name to distinguish worktrees"
199+
if [ -n "$folder_override" ] && [ -n "$custom_name" ]; then
200+
log_error "--folder and --name cannot be used together"
201+
exit 1
202+
fi
203+
204+
if [ "$force" -eq 1 ] && [ -z "$custom_name" ] && [ -z "$folder_override" ]; then
205+
log_error "--force requires --name or --folder to distinguish worktrees"
196206
if [ -n "$branch_name" ]; then
197207
echo "Example: git gtr new $branch_name --force --name backend" >&2
208+
echo " or: git gtr new $branch_name --force --folder my-folder" >&2
198209
else
199210
echo "Example: git gtr new feature-auth --force --name backend" >&2
211+
echo " or: git gtr new feature-auth --force --folder my-folder" >&2
200212
fi
201213
exit 1
202214
fi
@@ -245,7 +257,9 @@ cmd_create() {
245257

246258
# Construct folder name for display
247259
local folder_name
248-
if [ -n "$custom_name" ]; then
260+
if [ -n "$folder_override" ]; then
261+
folder_name=$(sanitize_branch_name "$folder_override")
262+
elif [ -n "$custom_name" ]; then
249263
folder_name="$(sanitize_branch_name "$branch_name")-${custom_name}"
250264
else
251265
folder_name=$(sanitize_branch_name "$branch_name")
@@ -256,7 +270,7 @@ cmd_create() {
256270
echo "Branch: $branch_name"
257271

258272
# Create the worktree
259-
if ! worktree_path=$(create_worktree "$base_dir" "$prefix" "$branch_name" "$from_ref" "$track_mode" "$skip_fetch" "$force" "$custom_name"); then
273+
if ! worktree_path=$(create_worktree "$base_dir" "$prefix" "$branch_name" "$from_ref" "$track_mode" "$skip_fetch" "$force" "$custom_name" "$folder_override"); then
260274
exit 1
261275
fi
262276

@@ -336,11 +350,20 @@ cmd_create() {
336350

337351
# Show next steps only if no auto-launch flags were used
338352
if [ "$open_editor" -eq 0 ] && [ "$start_ai" -eq 0 ]; then
353+
# Determine identifier to show in next steps
354+
# Use custom folder when --folder specified, otherwise use original branch name
355+
local next_steps_id
356+
if [ -n "$folder_override" ]; then
357+
next_steps_id="$folder_name"
358+
else
359+
next_steps_id="$branch_name"
360+
fi
361+
339362
echo ""
340363
echo "Next steps:"
341-
echo " git gtr editor $branch_name # Open in editor"
342-
echo " git gtr ai $branch_name # Start AI tool"
343-
echo " cd \"\$(git gtr go $branch_name)\" # Navigate to worktree"
364+
echo " git gtr editor $next_steps_id # Open in editor"
365+
echo " git gtr ai $next_steps_id # Start AI tool"
366+
echo " cd \"\$(git gtr go $next_steps_id)\" # Navigate to worktree"
344367
fi
345368
}
346369

@@ -1440,8 +1463,9 @@ CORE COMMANDS (daily workflow):
14401463
--track <mode>: tracking mode (auto|remote|local|none)
14411464
--no-copy: skip file copying
14421465
--no-fetch: skip git fetch
1443-
--force: allow same branch in multiple worktrees (requires --name)
1466+
--force: allow same branch in multiple worktrees (requires --name or --folder)
14441467
--name <suffix>: custom folder name suffix (e.g., backend, frontend)
1468+
--folder <name>: custom folder name (replaces default, useful for long branches)
14451469
--yes: non-interactive mode
14461470
-e, --editor: open in editor after creation
14471471
-a, --ai: start AI tool after creation

completions/_git-gtr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ _git-gtr() {
5050
'--no-fetch[Skip git fetch]' \
5151
'--force[Allow same branch in multiple worktrees]' \
5252
'--name[Custom folder name suffix]:name:' \
53+
'--folder[Custom folder name (replaces default)]:folder:' \
5354
'--yes[Non-interactive mode]' \
5455
'--editor[Open in editor after creation]' \
5556
'-e[Open in editor after creation]' \

completions/git-gtr.fish

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ complete -c git -n '__fish_git_gtr_using_command new' -l no-copy -d 'Skip file c
5555
complete -c git -n '__fish_git_gtr_using_command new' -l no-fetch -d 'Skip git fetch'
5656
complete -c git -n '__fish_git_gtr_using_command new' -l force -d 'Allow same branch in multiple worktrees'
5757
complete -c git -n '__fish_git_gtr_using_command new' -l name -d 'Custom folder name suffix' -r
58+
complete -c git -n '__fish_git_gtr_using_command new' -l folder -d 'Custom folder name (replaces default)' -r
5859
complete -c git -n '__fish_git_gtr_using_command new' -l yes -d 'Non-interactive mode'
5960
complete -c git -n '__fish_git_gtr_using_command new' -s e -l editor -d 'Open in editor after creation'
6061
complete -c git -n '__fish_git_gtr_using_command new' -s a -l ai -d 'Start AI tool after creation'

completions/gtr.bash

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ _git_gtr() {
5959
new)
6060
# Complete flags
6161
if [[ "$cur" == -* ]]; then
62-
COMPREPLY=($(compgen -W "--id --from --from-current --track --no-copy --no-fetch --force --name --yes --editor -e --ai -a" -- "$cur"))
62+
COMPREPLY=($(compgen -W "--id --from --from-current --track --no-copy --no-fetch --force --name --folder --yes --editor -e --ai -a" -- "$cur"))
6363
elif [ "$prev" = "--track" ]; then
6464
COMPREPLY=($(compgen -W "auto remote local none" -- "$cur"))
6565
fi

lib/core.sh

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,11 +272,12 @@ resolve_target() {
272272
}
273273

274274
# Create a new git worktree
275-
# Usage: create_worktree base_dir prefix branch_name from_ref track_mode [skip_fetch] [force] [custom_name]
275+
# Usage: create_worktree base_dir prefix branch_name from_ref track_mode [skip_fetch] [force] [custom_name] [folder_override]
276276
# track_mode: auto, remote, local, or none
277277
# skip_fetch: 0 (default, fetch) or 1 (skip)
278278
# force: 0 (default, check branch) or 1 (allow same branch in multiple worktrees)
279279
# custom_name: optional custom name suffix (e.g., "backend" creates "feature-auth-backend")
280+
# folder_override: optional complete folder name override (replaces default naming)
280281
create_worktree() {
281282
local base_dir="$1"
282283
local prefix="$2"
@@ -286,10 +287,13 @@ create_worktree() {
286287
local skip_fetch="${6:-0}"
287288
local force="${7:-0}"
288289
local custom_name="${8:-}"
290+
local folder_override="${9:-}"
289291
local sanitized_name worktree_path
290292

291293
# Construct folder name
292-
if [ -n "$custom_name" ]; then
294+
if [ -n "$folder_override" ]; then
295+
sanitized_name=$(sanitize_branch_name "$folder_override")
296+
elif [ -n "$custom_name" ]; then
293297
sanitized_name="$(sanitize_branch_name "$branch_name")-${custom_name}"
294298
else
295299
sanitized_name=$(sanitize_branch_name "$branch_name")

0 commit comments

Comments
 (0)