worktree-aid 1.2__tar.gz → 1.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: worktree-aid
3
- Version: 1.2
3
+ Version: 1.4
4
4
  Summary: Linux command line tool to aid creating, switching, and removing git worktrees
5
5
  Author-email: Mark Blakeney <mark.blakeney@bullet-systems.net>
6
6
  License-Expression: GPL-3.0-or-later
@@ -34,7 +34,7 @@ use to manage git worktrees. There are 3 commands typically used:
34
34
  - `wt rm` (or `wt r`) to remove a worktree + branch. If you don't specify a
35
35
  worktree name, then a [fuzzy finder][fzf] will prompt you with a list of
36
36
  worktrees to select from. The current worktree is first in the list and is the
37
- default selection to remove. If you delete the current worktree then you will
37
+ default selection to remove. If you remove the current worktree then you will
38
38
  be automatically cd'd to the toplevel repository directory.
39
39
 
40
40
  There are some other options and commands available, as described in later
@@ -49,7 +49,7 @@ https://github.com/bulletmark/worktree-aid.
49
49
  Type `wt` or `wt -h` to view the usage summary:
50
50
 
51
51
  ```
52
- usage: wt [-B BASEDIR] [-R] [-U] [-F FUZZY] [-h] [-v]
52
+ usage: wt [-B BASEDIR] [-R] [-r] [-U] [-u] [-F FUZZY] [-h] [-v]
53
53
  {add,a,rm,r,cd,c,ls,l,init} ...
54
54
 
55
55
  Linux command line tool to conveniently add, remove, and change directories
@@ -61,7 +61,9 @@ options:
61
61
  base directory for newly added worktrees,
62
62
  default="../worktrees/{repo}".
63
63
  -R, --relative display worktree paths relative instead of absolute
64
+ -r toggle -R/--relative option for one-off command only
64
65
  -U, --no-user do not substitute "~" for home directory
66
+ -u toggle -U/--no-user option for one-off command only
65
67
  -F, --fuzzy FUZZY fuzzy finder program, default="fzf"
66
68
  -h, --help show help message and exit
67
69
  -v, --version show program version and exit
@@ -81,7 +83,7 @@ individual command:
81
83
  ### Command `add`
82
84
 
83
85
  ```
84
- usage: wt add [-h] [-d] [-c] [worktree]
86
+ usage: wt add [-h] [-d] [-c] [worktree ...]
85
87
 
86
88
  Add new worktree + branch.
87
89
 
@@ -100,7 +102,7 @@ aliases: a
100
102
  ### Command `rm`
101
103
 
102
104
  ```
103
- usage: wt rm [-h] [-k] [-f] [worktree]
105
+ usage: wt rm [-h] [-k] [-f] [-a] [worktree ...]
104
106
 
105
107
  Remove worktree + branch.
106
108
 
@@ -114,6 +116,7 @@ options:
114
116
  -k, --keep-branch remove worktree but keep branch
115
117
  -f, --force force removal of worktree + branch even if untracked or
116
118
  unmerged changes exist.
119
+ -a, --all remove all worktrees
117
120
 
118
121
  aliases: r
119
122
  ```
@@ -187,16 +190,17 @@ $ yay -S worktree-aid # or your preferred AUR helper
187
190
  ```
188
191
 
189
192
  You also need to install a fuzzy finder program such as [`fzf`][fzf] which is
190
- the default used by `worktree-aid`. See [fuzzy finder installation
191
- instructions](#fuzzy-finder-integration) for possible alternatives.
193
+ the default used by `worktree-aid`. See [fuzzy finder
194
+ installation](#fuzzy-finder-integration) instructions for possible
195
+ alternatives.
192
196
 
193
197
  ## Setup
194
198
 
195
199
  A user who wants to use `worktree-aid` must add the following line to their
196
200
  `~/.bashrc` (`bash` user) or `~/.zshrc` (`zsh` user). Ensure it is added
197
- after where your PATH is set up so that the command `worktree-aid` can be found. This
198
- creates the `wt` wrapper command in your interactive shell session as a tiny
199
- function.
201
+ after where your PATH is set up so that the command `worktree-aid` can be
202
+ found. This creates the `wt` wrapper command in your interactive shell session
203
+ as a tiny function.
200
204
 
201
205
  ```sh
202
206
  source <(worktree-aid init)
@@ -229,15 +233,11 @@ initialization code, e.g:
229
233
  source <(worktree-aid init "wt -R")
230
234
  ```
231
235
 
232
- The above sets `-R` (for relative display of worktree directories) as default for your
233
- `wt` command.
236
+ The above sets `-R` (for relative display of worktree directories) as default
237
+ for your `wt` command.
234
238
 
235
239
  The following options are sensible candidates to set as default options:
236
-
237
- - `-B/--basedir`,
238
- - `-R/--relative`,
239
- - `-U/--no-user`,
240
- - `-F/--fuzzy`.
240
+ `-B/--basedir`, `-R/--relative`, `-U/--no-user`, `-F/--fuzzy`.
241
241
 
242
242
  ## Worktree Base Directory
243
243
 
@@ -246,18 +246,25 @@ worktrees. It is set to a default as below but you can change this to any
246
246
  directory you like. It can be absolute or relative where relative paths are
247
247
  relative to base repository directory.
248
248
 
249
- - Default is `-B ../worktrees/{repo}` which is the same as the [Zed] editor uses.
250
- - E.g. can use `-B ../{repo}.worktrees` which is same as [VS Code] uses.
251
- - E.g. can use `-B ~/worktrees/{repo}` to put all worktrees in a subdirectory of your home directory.
249
+ - Default base directory is `-B ../worktrees/{repo}`.
250
+ - E.g. can use `-B ../{repo}.worktrees` which is same as [VS Code] uses by
251
+ default.
252
+ - E.g. can use `-B ~/worktrees/{repo}` to put all worktrees within a
253
+ subdirectory of your home directory.
252
254
 
253
255
  The following place-markers can be used in the definition of the base directory:
254
256
 
255
257
  - `{repo}`: Substituted with the base name of the repository.
256
258
  - `{user}`: Substituted with the name of the user.
257
- - `{home}`: Substituted with the home directory of the user (also can use `~` at start of a path).
259
+ - `{home}`: Substituted with the home directory of the user (also can use `~`
260
+ at start of a path).
261
+
262
+ Most likely if you want to set a custom base directory then you will set `-B`
263
+ as a [default option](#default-options).
258
264
 
259
- Most likely if you want to set a custom basedir then you will set `-B` as a
260
- [default option](#default-options).
265
+ Note that the `--B/--basedir` setting is only relevant when adding a new
266
+ worktree using the `add` command. All other commands query your existing
267
+ worktrees so will work regardless of how or where the worktrees were created.
261
268
 
262
269
  ## Display as Relative Worktree Directories
263
270
 
@@ -268,13 +275,15 @@ can enable it in `worktree-aid` by adding the `-R/--relative` option, e.g:
268
275
 
269
276
  ```sh
270
277
  $ wt l
271
- ../development 9796714 [development]
272
- ../milestone1 bc921b8 [milestone1]
273
- ../test e6d965a [test]
274
- . f76b8e0 [main]
278
+ ../worktrees/worktree-aid/development 9796714 [development]
279
+ ../worktrees/worktree-aid/milestone1 bc921b8 [milestone1]
280
+ ../worktrees/worktree-aid/test e6d965a [test]
281
+ f76b8e0 [main]
275
282
  ```
276
283
 
277
284
  Most likely you will want to set `-R` as a [default option](#default-options).
285
+ Note you can use the `-r` option on a one-off command to temporarily toggle
286
+ whatever your default `-R/--relative` option is set as.
278
287
 
279
288
  ## Fuzzy Finder Integration
280
289
 
@@ -22,7 +22,7 @@ use to manage git worktrees. There are 3 commands typically used:
22
22
  - `wt rm` (or `wt r`) to remove a worktree + branch. If you don't specify a
23
23
  worktree name, then a [fuzzy finder][fzf] will prompt you with a list of
24
24
  worktrees to select from. The current worktree is first in the list and is the
25
- default selection to remove. If you delete the current worktree then you will
25
+ default selection to remove. If you remove the current worktree then you will
26
26
  be automatically cd'd to the toplevel repository directory.
27
27
 
28
28
  There are some other options and commands available, as described in later
@@ -37,7 +37,7 @@ https://github.com/bulletmark/worktree-aid.
37
37
  Type `wt` or `wt -h` to view the usage summary:
38
38
 
39
39
  ```
40
- usage: wt [-B BASEDIR] [-R] [-U] [-F FUZZY] [-h] [-v]
40
+ usage: wt [-B BASEDIR] [-R] [-r] [-U] [-u] [-F FUZZY] [-h] [-v]
41
41
  {add,a,rm,r,cd,c,ls,l,init} ...
42
42
 
43
43
  Linux command line tool to conveniently add, remove, and change directories
@@ -49,7 +49,9 @@ options:
49
49
  base directory for newly added worktrees,
50
50
  default="../worktrees/{repo}".
51
51
  -R, --relative display worktree paths relative instead of absolute
52
+ -r toggle -R/--relative option for one-off command only
52
53
  -U, --no-user do not substitute "~" for home directory
54
+ -u toggle -U/--no-user option for one-off command only
53
55
  -F, --fuzzy FUZZY fuzzy finder program, default="fzf"
54
56
  -h, --help show help message and exit
55
57
  -v, --version show program version and exit
@@ -69,7 +71,7 @@ individual command:
69
71
  ### Command `add`
70
72
 
71
73
  ```
72
- usage: wt add [-h] [-d] [-c] [worktree]
74
+ usage: wt add [-h] [-d] [-c] [worktree ...]
73
75
 
74
76
  Add new worktree + branch.
75
77
 
@@ -88,7 +90,7 @@ aliases: a
88
90
  ### Command `rm`
89
91
 
90
92
  ```
91
- usage: wt rm [-h] [-k] [-f] [worktree]
93
+ usage: wt rm [-h] [-k] [-f] [-a] [worktree ...]
92
94
 
93
95
  Remove worktree + branch.
94
96
 
@@ -102,6 +104,7 @@ options:
102
104
  -k, --keep-branch remove worktree but keep branch
103
105
  -f, --force force removal of worktree + branch even if untracked or
104
106
  unmerged changes exist.
107
+ -a, --all remove all worktrees
105
108
 
106
109
  aliases: r
107
110
  ```
@@ -175,16 +178,17 @@ $ yay -S worktree-aid # or your preferred AUR helper
175
178
  ```
176
179
 
177
180
  You also need to install a fuzzy finder program such as [`fzf`][fzf] which is
178
- the default used by `worktree-aid`. See [fuzzy finder installation
179
- instructions](#fuzzy-finder-integration) for possible alternatives.
181
+ the default used by `worktree-aid`. See [fuzzy finder
182
+ installation](#fuzzy-finder-integration) instructions for possible
183
+ alternatives.
180
184
 
181
185
  ## Setup
182
186
 
183
187
  A user who wants to use `worktree-aid` must add the following line to their
184
188
  `~/.bashrc` (`bash` user) or `~/.zshrc` (`zsh` user). Ensure it is added
185
- after where your PATH is set up so that the command `worktree-aid` can be found. This
186
- creates the `wt` wrapper command in your interactive shell session as a tiny
187
- function.
189
+ after where your PATH is set up so that the command `worktree-aid` can be
190
+ found. This creates the `wt` wrapper command in your interactive shell session
191
+ as a tiny function.
188
192
 
189
193
  ```sh
190
194
  source <(worktree-aid init)
@@ -217,15 +221,11 @@ initialization code, e.g:
217
221
  source <(worktree-aid init "wt -R")
218
222
  ```
219
223
 
220
- The above sets `-R` (for relative display of worktree directories) as default for your
221
- `wt` command.
224
+ The above sets `-R` (for relative display of worktree directories) as default
225
+ for your `wt` command.
222
226
 
223
227
  The following options are sensible candidates to set as default options:
224
-
225
- - `-B/--basedir`,
226
- - `-R/--relative`,
227
- - `-U/--no-user`,
228
- - `-F/--fuzzy`.
228
+ `-B/--basedir`, `-R/--relative`, `-U/--no-user`, `-F/--fuzzy`.
229
229
 
230
230
  ## Worktree Base Directory
231
231
 
@@ -234,18 +234,25 @@ worktrees. It is set to a default as below but you can change this to any
234
234
  directory you like. It can be absolute or relative where relative paths are
235
235
  relative to base repository directory.
236
236
 
237
- - Default is `-B ../worktrees/{repo}` which is the same as the [Zed] editor uses.
238
- - E.g. can use `-B ../{repo}.worktrees` which is same as [VS Code] uses.
239
- - E.g. can use `-B ~/worktrees/{repo}` to put all worktrees in a subdirectory of your home directory.
237
+ - Default base directory is `-B ../worktrees/{repo}`.
238
+ - E.g. can use `-B ../{repo}.worktrees` which is same as [VS Code] uses by
239
+ default.
240
+ - E.g. can use `-B ~/worktrees/{repo}` to put all worktrees within a
241
+ subdirectory of your home directory.
240
242
 
241
243
  The following place-markers can be used in the definition of the base directory:
242
244
 
243
245
  - `{repo}`: Substituted with the base name of the repository.
244
246
  - `{user}`: Substituted with the name of the user.
245
- - `{home}`: Substituted with the home directory of the user (also can use `~` at start of a path).
247
+ - `{home}`: Substituted with the home directory of the user (also can use `~`
248
+ at start of a path).
249
+
250
+ Most likely if you want to set a custom base directory then you will set `-B`
251
+ as a [default option](#default-options).
246
252
 
247
- Most likely if you want to set a custom basedir then you will set `-B` as a
248
- [default option](#default-options).
253
+ Note that the `--B/--basedir` setting is only relevant when adding a new
254
+ worktree using the `add` command. All other commands query your existing
255
+ worktrees so will work regardless of how or where the worktrees were created.
249
256
 
250
257
  ## Display as Relative Worktree Directories
251
258
 
@@ -256,13 +263,15 @@ can enable it in `worktree-aid` by adding the `-R/--relative` option, e.g:
256
263
 
257
264
  ```sh
258
265
  $ wt l
259
- ../development 9796714 [development]
260
- ../milestone1 bc921b8 [milestone1]
261
- ../test e6d965a [test]
262
- . f76b8e0 [main]
266
+ ../worktrees/worktree-aid/development 9796714 [development]
267
+ ../worktrees/worktree-aid/milestone1 bc921b8 [milestone1]
268
+ ../worktrees/worktree-aid/test e6d965a [test]
269
+ f76b8e0 [main]
263
270
  ```
264
271
 
265
272
  Most likely you will want to set `-R` as a [default option](#default-options).
273
+ Note you can use the `-r` option on a one-off command to temporarily toggle
274
+ whatever your default `-R/--relative` option is set as.
266
275
 
267
276
  ## Fuzzy Finder Integration
268
277
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: worktree-aid
3
- Version: 1.2
3
+ Version: 1.4
4
4
  Summary: Linux command line tool to aid creating, switching, and removing git worktrees
5
5
  Author-email: Mark Blakeney <mark.blakeney@bullet-systems.net>
6
6
  License-Expression: GPL-3.0-or-later
@@ -34,7 +34,7 @@ use to manage git worktrees. There are 3 commands typically used:
34
34
  - `wt rm` (or `wt r`) to remove a worktree + branch. If you don't specify a
35
35
  worktree name, then a [fuzzy finder][fzf] will prompt you with a list of
36
36
  worktrees to select from. The current worktree is first in the list and is the
37
- default selection to remove. If you delete the current worktree then you will
37
+ default selection to remove. If you remove the current worktree then you will
38
38
  be automatically cd'd to the toplevel repository directory.
39
39
 
40
40
  There are some other options and commands available, as described in later
@@ -49,7 +49,7 @@ https://github.com/bulletmark/worktree-aid.
49
49
  Type `wt` or `wt -h` to view the usage summary:
50
50
 
51
51
  ```
52
- usage: wt [-B BASEDIR] [-R] [-U] [-F FUZZY] [-h] [-v]
52
+ usage: wt [-B BASEDIR] [-R] [-r] [-U] [-u] [-F FUZZY] [-h] [-v]
53
53
  {add,a,rm,r,cd,c,ls,l,init} ...
54
54
 
55
55
  Linux command line tool to conveniently add, remove, and change directories
@@ -61,7 +61,9 @@ options:
61
61
  base directory for newly added worktrees,
62
62
  default="../worktrees/{repo}".
63
63
  -R, --relative display worktree paths relative instead of absolute
64
+ -r toggle -R/--relative option for one-off command only
64
65
  -U, --no-user do not substitute "~" for home directory
66
+ -u toggle -U/--no-user option for one-off command only
65
67
  -F, --fuzzy FUZZY fuzzy finder program, default="fzf"
66
68
  -h, --help show help message and exit
67
69
  -v, --version show program version and exit
@@ -81,7 +83,7 @@ individual command:
81
83
  ### Command `add`
82
84
 
83
85
  ```
84
- usage: wt add [-h] [-d] [-c] [worktree]
86
+ usage: wt add [-h] [-d] [-c] [worktree ...]
85
87
 
86
88
  Add new worktree + branch.
87
89
 
@@ -100,7 +102,7 @@ aliases: a
100
102
  ### Command `rm`
101
103
 
102
104
  ```
103
- usage: wt rm [-h] [-k] [-f] [worktree]
105
+ usage: wt rm [-h] [-k] [-f] [-a] [worktree ...]
104
106
 
105
107
  Remove worktree + branch.
106
108
 
@@ -114,6 +116,7 @@ options:
114
116
  -k, --keep-branch remove worktree but keep branch
115
117
  -f, --force force removal of worktree + branch even if untracked or
116
118
  unmerged changes exist.
119
+ -a, --all remove all worktrees
117
120
 
118
121
  aliases: r
119
122
  ```
@@ -187,16 +190,17 @@ $ yay -S worktree-aid # or your preferred AUR helper
187
190
  ```
188
191
 
189
192
  You also need to install a fuzzy finder program such as [`fzf`][fzf] which is
190
- the default used by `worktree-aid`. See [fuzzy finder installation
191
- instructions](#fuzzy-finder-integration) for possible alternatives.
193
+ the default used by `worktree-aid`. See [fuzzy finder
194
+ installation](#fuzzy-finder-integration) instructions for possible
195
+ alternatives.
192
196
 
193
197
  ## Setup
194
198
 
195
199
  A user who wants to use `worktree-aid` must add the following line to their
196
200
  `~/.bashrc` (`bash` user) or `~/.zshrc` (`zsh` user). Ensure it is added
197
- after where your PATH is set up so that the command `worktree-aid` can be found. This
198
- creates the `wt` wrapper command in your interactive shell session as a tiny
199
- function.
201
+ after where your PATH is set up so that the command `worktree-aid` can be
202
+ found. This creates the `wt` wrapper command in your interactive shell session
203
+ as a tiny function.
200
204
 
201
205
  ```sh
202
206
  source <(worktree-aid init)
@@ -229,15 +233,11 @@ initialization code, e.g:
229
233
  source <(worktree-aid init "wt -R")
230
234
  ```
231
235
 
232
- The above sets `-R` (for relative display of worktree directories) as default for your
233
- `wt` command.
236
+ The above sets `-R` (for relative display of worktree directories) as default
237
+ for your `wt` command.
234
238
 
235
239
  The following options are sensible candidates to set as default options:
236
-
237
- - `-B/--basedir`,
238
- - `-R/--relative`,
239
- - `-U/--no-user`,
240
- - `-F/--fuzzy`.
240
+ `-B/--basedir`, `-R/--relative`, `-U/--no-user`, `-F/--fuzzy`.
241
241
 
242
242
  ## Worktree Base Directory
243
243
 
@@ -246,18 +246,25 @@ worktrees. It is set to a default as below but you can change this to any
246
246
  directory you like. It can be absolute or relative where relative paths are
247
247
  relative to base repository directory.
248
248
 
249
- - Default is `-B ../worktrees/{repo}` which is the same as the [Zed] editor uses.
250
- - E.g. can use `-B ../{repo}.worktrees` which is same as [VS Code] uses.
251
- - E.g. can use `-B ~/worktrees/{repo}` to put all worktrees in a subdirectory of your home directory.
249
+ - Default base directory is `-B ../worktrees/{repo}`.
250
+ - E.g. can use `-B ../{repo}.worktrees` which is same as [VS Code] uses by
251
+ default.
252
+ - E.g. can use `-B ~/worktrees/{repo}` to put all worktrees within a
253
+ subdirectory of your home directory.
252
254
 
253
255
  The following place-markers can be used in the definition of the base directory:
254
256
 
255
257
  - `{repo}`: Substituted with the base name of the repository.
256
258
  - `{user}`: Substituted with the name of the user.
257
- - `{home}`: Substituted with the home directory of the user (also can use `~` at start of a path).
259
+ - `{home}`: Substituted with the home directory of the user (also can use `~`
260
+ at start of a path).
261
+
262
+ Most likely if you want to set a custom base directory then you will set `-B`
263
+ as a [default option](#default-options).
258
264
 
259
- Most likely if you want to set a custom basedir then you will set `-B` as a
260
- [default option](#default-options).
265
+ Note that the `--B/--basedir` setting is only relevant when adding a new
266
+ worktree using the `add` command. All other commands query your existing
267
+ worktrees so will work regardless of how or where the worktrees were created.
261
268
 
262
269
  ## Display as Relative Worktree Directories
263
270
 
@@ -268,13 +275,15 @@ can enable it in `worktree-aid` by adding the `-R/--relative` option, e.g:
268
275
 
269
276
  ```sh
270
277
  $ wt l
271
- ../development 9796714 [development]
272
- ../milestone1 bc921b8 [milestone1]
273
- ../test e6d965a [test]
274
- . f76b8e0 [main]
278
+ ../worktrees/worktree-aid/development 9796714 [development]
279
+ ../worktrees/worktree-aid/milestone1 bc921b8 [milestone1]
280
+ ../worktrees/worktree-aid/test e6d965a [test]
281
+ f76b8e0 [main]
275
282
  ```
276
283
 
277
284
  Most likely you will want to set `-R` as a [default option](#default-options).
285
+ Note you can use the `-r` option on a one-off command to temporarily toggle
286
+ whatever your default `-R/--relative` option is set as.
278
287
 
279
288
  ## Fuzzy Finder Integration
280
289
 
@@ -0,0 +1,8 @@
1
+ {
2
+ "tag": "1.4",
3
+ "distance": 0,
4
+ "node": "ga5a7f880491682fdb2eb9c3ee49154b0a37b2e29",
5
+ "dirty": false,
6
+ "branch": "main",
7
+ "node_date": "2026-08-04"
8
+ }
@@ -145,6 +145,15 @@ def print_help(args: Namespace) -> None:
145
145
  args._opt.print_help(sys.stderr)
146
146
 
147
147
 
148
+ def validate_name(name: str) -> None:
149
+ "Ensure worktree name is valid"
150
+ if ' ' in name:
151
+ sys.exit(f'error: worktree name "{name}" can not contain spaces.')
152
+
153
+ if '/' in name or '\\' in name:
154
+ sys.exit(f'error: worktree name "{name}" can not contain "/" or "\\".')
155
+
156
+
148
157
  @dataclass
149
158
  class Tree:
150
159
  "Data for an individual worktree"
@@ -158,16 +167,9 @@ class Tree:
158
167
  class Trees:
159
168
  "Class to manage the collection of worktrees"
160
169
 
161
- trees: list[Tree]
162
- names: dict[str, Tree]
163
- toplevel: Tree
164
- current: Tree
165
-
166
- @classmethod
167
- def fetch(cls, args: Namespace) -> None:
170
+ def __init__(self, args: Namespace) -> None:
168
171
  "Get worktrees"
169
172
  trees = []
170
- names = {}
171
173
  tree = None
172
174
  cwdparts = Path.cwd().parts
173
175
  phere = pindex = -1
@@ -196,9 +198,6 @@ class Trees:
196
198
  pindex = len(trees)
197
199
 
198
200
  trees.append(tree := Tree(path, path_display))
199
-
200
- if (name := path.name) not in names or name == tree.branch:
201
- names[name] = tree
202
201
  elif tree:
203
202
  if field == 'HEAD':
204
203
  tree.head = value[:HASH_LEN]
@@ -210,21 +209,19 @@ class Trees:
210
209
 
211
210
  if pindex > 0:
212
211
  trees = [trees[pindex]] + trees[:pindex] + trees[pindex + 1 :]
213
- cls.toplevel = trees[1]
212
+ self.toplevel = trees[1]
214
213
  else:
215
- cls.toplevel = trees[0]
214
+ self.toplevel = trees[0]
216
215
 
217
- cls.current = trees[0]
218
- cls.trees = trees
219
- cls.names = names
216
+ self.trees = trees
217
+ self.current = trees[0]
220
218
 
221
- @classmethod
222
- def get_trees(cls) -> list[str]:
219
+ def get_trees(self) -> list[str]:
223
220
  "Fetch string list of worktrees"
224
- pw = max(len(str(t.path_display)) for t in cls.trees)
225
- lines = []
226
- for t in cls.trees:
227
- tlist = [f'{t.path_display:{pw}}']
221
+ width = max(len(str(t.path_display)) for t in self.trees)
222
+ trees = []
223
+ for t in self.trees:
224
+ tlist = [f'{t.path_display:{width}}']
228
225
  if t.head:
229
226
  tlist.append(t.head)
230
227
  if t.branch:
@@ -232,35 +229,43 @@ class Trees:
232
229
  else:
233
230
  tlist.append('detached')
234
231
 
235
- lines.append(' '.join(tlist))
232
+ trees.append(' '.join(tlist))
236
233
 
237
- return lines
234
+ return trees
238
235
 
239
- @classmethod
240
- def get_tree(cls, name: str) -> Tree | None:
236
+ def get_tree(self, name: str) -> Tree | None:
241
237
  "Return worktree with given name, or None if not found"
242
- return cls.current if cls.current.path.name == name else cls.names.get(name)
238
+ path_match = None
239
+ for tree in self.trees:
240
+ if tree.branch == name:
241
+ return tree
242
+
243
+ if tree.path.name == name:
244
+ path_match = tree
245
+
246
+ return path_match
243
247
 
244
- @classmethod
245
- def create_worktree(cls, name: str, args: Namespace) -> Path:
248
+ def create_worktree(self, name: str, args: Namespace) -> Path:
246
249
  "Create a new worktree and branch with the given name"
247
250
  if not name:
248
251
  # If no name is given, generate a new name that does not conflict
249
252
  # with existing worktrees or branches
250
- existing = {t.path.name for t in cls.trees}
253
+ existing = {t.path.name for t in self.trees}
251
254
  branches = run('git --no-pager branch --list'.split()).splitlines()
252
- existing.update(b.split(maxsplit=1)[1] for b in branches)
255
+ existing.update(b.split(maxsplit=1)[-1] for b in branches)
253
256
  name = generate_new_name(existing)
257
+ else:
258
+ validate_name(name)
254
259
 
255
260
  try:
256
261
  basedir = args.basedir.format(
257
- user=getpass.getuser(), repo=cls.toplevel.path.name, home=str(HOME)
262
+ user=getpass.getuser(), repo=self.toplevel.path.name, home=str(HOME)
258
263
  )
259
264
  except Exception as e:
260
265
  sys.exit(f'error: failed to format basedir: {e}')
261
266
 
262
267
  basepath = Path(basedir).expanduser()
263
- basepath = (cls.toplevel.path / basepath).resolve()
268
+ basepath = (self.toplevel.path / basepath).resolve()
264
269
  basepath.mkdir(parents=True, exist_ok=True)
265
270
  path = basepath / name
266
271
 
@@ -270,19 +275,23 @@ class Trees:
270
275
  run(cmd + [str(path)], stdout=args._stdout)
271
276
  return path
272
277
 
273
- @classmethod
274
- def remove_worktree(cls, name: str, args: Namespace) -> Path | None:
278
+ def remove_worktree(
279
+ self, name: str, args: Namespace, tree: Tree | None = None
280
+ ) -> Path | None:
275
281
  "Remove the worktree and branch with the given name"
276
- if name:
277
- if not (tree := cls.get_tree(name)):
278
- sys.exit(f'error: no worktree found with name "{name}".')
279
- else:
280
- # If no name is given, remove the current worktree and branch
281
- tree = cls.current
282
+ if not tree and not (tree := self.get_tree(name)):
283
+ sys.exit(f'error: no worktree found with name "{name}".')
284
+
285
+ if tree == self.toplevel:
286
+ print(
287
+ f'warning: not removing top-level worktree "{tree.path}"',
288
+ file=sys.stderr,
289
+ )
290
+ return None
282
291
 
283
292
  # Change to the top-level worktree directory before deleting a worktree
284
293
  # and/or branch, in case the current directory is removed.
285
- os.chdir(cls.toplevel.path)
294
+ os.chdir(self.toplevel.path)
286
295
 
287
296
  cmd = 'git worktree remove'.split()
288
297
  if args.force:
@@ -297,19 +306,18 @@ class Trees:
297
306
  cmd = 'git branch'.split() + ['-D' if args.force else '-d']
298
307
  run(cmd + [tree.branch], stdout=args._stdout, ignore_error=True)
299
308
 
300
- return cls.toplevel.path if tree == cls.current else None
309
+ return self.toplevel.path if tree == self.current else None
301
310
 
302
- @classmethod
303
- def prompt(cls, args: Namespace) -> Path | None:
311
+ def prompt(self, args: Namespace) -> Tree | None:
304
312
  "Prompt user to select a worktree using fuzzy finder"
305
- wtrees = cls.get_trees()
313
+ wtrees = self.get_trees()
306
314
  if not wtrees:
307
315
  sys.exit('error: no worktrees to remove.')
308
316
  line = run(shlex.split(args.fuzzy), stdin='\n'.join(wtrees)).strip()
309
317
  if not line or line not in wtrees:
310
318
  return None
311
319
 
312
- return cls.trees[wtrees.index(line)].path
320
+ return self.trees[wtrees.index(line)]
313
321
 
314
322
 
315
323
  def main() -> int:
@@ -335,12 +343,22 @@ def main() -> int:
335
343
  action='store_true',
336
344
  help='display worktree paths relative instead of absolute',
337
345
  )
346
+ opt.add_argument(
347
+ '-r',
348
+ action='store_true',
349
+ help='toggle -R/--relative option for one-off command only',
350
+ )
338
351
  opt.add_argument(
339
352
  '-U',
340
353
  '--no-user',
341
354
  action='store_true',
342
355
  help='do not substitute "~" for home directory',
343
356
  )
357
+ opt.add_argument(
358
+ '-u',
359
+ action='store_true',
360
+ help='toggle -U/--no-user option for one-off command only',
361
+ )
344
362
  opt.add_argument(
345
363
  '-F',
346
364
  '--fuzzy',
@@ -389,6 +407,13 @@ def main() -> int:
389
407
 
390
408
  args = opt.parse_args()
391
409
  args._opt = opt
410
+
411
+ if args.r:
412
+ args.relative = not args.relative
413
+
414
+ if args.u:
415
+ args.no_user = not args.no_user
416
+
392
417
  if args._:
393
418
  try:
394
419
  args._stdout = open('/dev/tty', 'w')
@@ -437,16 +462,19 @@ class add_:
437
462
  )
438
463
  parser.add_argument(
439
464
  'worktree',
440
- default='',
441
- nargs='?',
465
+ nargs='*',
442
466
  help='new worktree + branch to add. A name is automatically created if not specified.',
443
467
  )
444
468
 
445
469
  @staticmethod
446
470
  def run(args: Namespace) -> str | None:
447
- Trees.fetch(args)
448
- path = Trees.create_worktree(args.worktree, args)
449
- return str(path) if path and not args.no_cd else None
471
+ trees = Trees(args)
472
+ retpath = None
473
+ for name in args.worktree or ['']:
474
+ if (path := trees.create_worktree(name, args)) and not retpath:
475
+ retpath = path
476
+
477
+ return str(retpath) if retpath and not args.no_cd else None
450
478
 
451
479
 
452
480
  # COMMAND
@@ -470,10 +498,15 @@ class rm_:
470
498
  help='force removal of worktree + branch even if '
471
499
  'untracked or unmerged changes exist.',
472
500
  )
501
+ parser.add_argument(
502
+ '-a',
503
+ '--all',
504
+ action='store_true',
505
+ help='remove all worktrees',
506
+ )
473
507
  parser.add_argument(
474
508
  'worktree',
475
- default='',
476
- nargs='?',
509
+ nargs='*',
477
510
  help='worktree + branch name to remove. If not specified then '
478
511
  'fuzzy finder will prompt with a list of worktrees, with the '
479
512
  'current worktree as the default selection.',
@@ -481,14 +514,29 @@ class rm_:
481
514
 
482
515
  @staticmethod
483
516
  def run(args: Namespace) -> str | None:
484
- Trees.fetch(args)
485
- if not (name := args.worktree):
486
- if not (path := Trees.prompt(args)):
517
+ trees = Trees(args)
518
+
519
+ if args.all:
520
+ if args.worktree:
521
+ sys.exit('error: cannot specify any worktree name with --all option.')
522
+
523
+ names = [t.path.name for t in trees.trees if t != trees.toplevel]
524
+ else:
525
+ names = args.worktree or ['']
526
+
527
+ retpath = None
528
+ tree = None
529
+ for name in names:
530
+ # If no worktree name is given, prompt user to select one
531
+ if not name and not (tree := trees.prompt(args)):
487
532
  return None
488
- name = path.name
489
533
 
490
- path = Trees.remove_worktree(name, args)
491
- return str(path) if path else None
534
+ if (path := trees.remove_worktree(name, args, tree)) and not retpath:
535
+ retpath = path
536
+
537
+ tree = None
538
+
539
+ return str(retpath) if retpath else None
492
540
 
493
541
 
494
542
  # COMMAND
@@ -509,18 +557,18 @@ class cd_:
509
557
 
510
558
  @staticmethod
511
559
  def run(args: Namespace) -> str | None:
512
- Trees.fetch(args)
560
+ trees = Trees(args)
513
561
  if name := args.worktree:
514
562
  if name == '/':
515
- path = Trees.toplevel.path
516
- elif tree := Trees.get_tree(name):
517
- path = tree.path
518
- else:
563
+ # Shortcut to top-level worktree
564
+ tree = trees.toplevel
565
+ elif not (tree := trees.get_tree(name)):
519
566
  sys.exit(f'error: no worktree found with name "{name}".')
520
567
  else:
521
- path = Trees.prompt(args)
568
+ # If no worktree name is given, prompt user to select one
569
+ tree = trees.prompt(args)
522
570
 
523
- return str(path) if path else None
571
+ return str(tree.path) if tree else None
524
572
 
525
573
 
526
574
  # COMMAND
@@ -531,9 +579,8 @@ class ls_:
531
579
 
532
580
  @staticmethod
533
581
  def run(args: Namespace) -> str | None:
534
- Trees.fetch(args)
535
- trees = Trees.get_trees()
536
- for line in reversed(trees):
582
+ trees = Trees(args)
583
+ for line in reversed(trees.get_trees()):
537
584
  print(line, file=args._stdout)
538
585
 
539
586
  return None
@@ -1,8 +0,0 @@
1
- {
2
- "tag": "1.2",
3
- "distance": 0,
4
- "node": "gcb78b4dc270eb62209b736dedbcf8e12ad2591ec",
5
- "dirty": false,
6
- "branch": "main",
7
- "node_date": "2026-08-02"
8
- }
File without changes
File without changes
File without changes
File without changes