git-worktrees 0.3.0__tar.gz → 0.4.0__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.
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/AGENTS.md +8 -4
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/CHANGELOG.md +59 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/PKG-INFO +48 -11
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/README.md +47 -10
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/docs/DEVELOPMENT.md +3 -1
- git_worktrees-0.4.0/docs/REFERENCE.md +438 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/pyproject.toml +1 -1
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/src/worktrees/cli.py +75 -21
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/src/worktrees/forge.py +9 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/src/worktrees/layout.py +37 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/src/worktrees/new_branch.py +4 -1
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/src/worktrees/pick.py +17 -1
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/src/worktrees/prune.py +6 -1
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/src/worktrees/verdicts.py +23 -1
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/tests/conftest.py +16 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/tests/test_cli.py +185 -11
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/tests/test_completions.py +45 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/tests/test_forge.py +114 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/tests/test_gates.py +31 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/tests/test_shims.py +28 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/tests/test_worktree.py +40 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/uv.lock +1 -1
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/.agents/skills/release/SKILL.md +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/.claude/settings.json +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/.github/workflows/publish.yml +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/.github/workflows/testpypi.yml +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/.github/workflows/tests.yml +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/.gitignore +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/.pre-commit-config.yaml +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/.python-version +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/LICENSE +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/completions/gw.fish +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/completions/gwa.fish +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/completions/gwh.fish +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/completions/gwl.fish +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/completions/gwm.fish +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/completions/gwnb.fish +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/completions/gwp.fish +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/completions/gwr.fish +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/completions/gwrot.fish +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/completions/gws.fish +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/conf.d/worktrees.fish +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/docs/BENCHMARK.md +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/functions/gwa.fish +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/functions/gwl.fish +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/functions/gwm.fish +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/functions/gwr.fish +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/hatch_build.py +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/renovate.json +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/scripts/README.md +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/scripts/benchmark.py +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/scripts/verify-publish.bash +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/src/worktrees/__init__.py +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/src/worktrees/errors.py +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/src/worktrees/git.py +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/src/worktrees/merged.py +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/src/worktrees/render.py +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/src/worktrees/repo.py +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/src/worktrees/rotate.py +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/src/worktrees/worktree.py +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/tests/test_benchmark.py +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/tests/test_fixture.py +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/tests/test_new_branch.py +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/tests/test_render.py +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/tests/test_rotate.py +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/tests/test_spec.py +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/tests/test_version.py +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/zsh/plugins/worktrees/completions/_gw +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/zsh/plugins/worktrees/completions/_gwa +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/zsh/plugins/worktrees/completions/_gwh +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/zsh/plugins/worktrees/completions/_gwl +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/zsh/plugins/worktrees/completions/_gwm +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/zsh/plugins/worktrees/completions/_gwnb +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/zsh/plugins/worktrees/completions/_gwp +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/zsh/plugins/worktrees/completions/_gwr +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/zsh/plugins/worktrees/completions/_gwrot +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/zsh/plugins/worktrees/completions/_gws +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/zsh/plugins/worktrees/functions/gwa +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/zsh/plugins/worktrees/functions/gwl +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/zsh/plugins/worktrees/functions/gwm +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/zsh/plugins/worktrees/functions/gwr +0 -0
- {git_worktrees-0.3.0 → git_worktrees-0.4.0}/zsh/plugins/worktrees/worktrees.plugin.zsh +0 -0
|
@@ -156,10 +156,14 @@ Two more about what is in the list at all:
|
|
|
156
156
|
the one a finished branch leaves you in, so leaving it out leaves out the
|
|
157
157
|
only answer that is always right. `main` finds it whatever branch it stands
|
|
158
158
|
on, because its label carries the word, once.
|
|
159
|
-
- The worktree you are standing in is
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
159
|
+
- The worktree you are standing in is shown and never offered. It carries a
|
|
160
|
+
`*` rather than a number, because picking it is the one answer that takes
|
|
161
|
+
you nowhere. Leaving it out of the list entirely is worse: the list then
|
|
162
|
+
shows fewer rows than `git worktree list` does, and reads as though
|
|
163
|
+
something went missing rather than as where you already are. The main
|
|
164
|
+
checkout is in `gws` and `gwp` for the same reason, kept and never
|
|
165
|
+
proposed, and out of `gwr`'s candidates because `git worktree remove`
|
|
166
|
+
refuses it whatever flag it is given.
|
|
163
167
|
|
|
164
168
|
`--json` and `--list` answer the same question without any of this, and an
|
|
165
169
|
agent uses those.
|
|
@@ -17,6 +17,65 @@ not in here, whatever it cost to build.
|
|
|
17
17
|
A release closes with a `### Choices` section when a decision in it is worth
|
|
18
18
|
the reader's time: what was chosen, and what the alternative failed to do.
|
|
19
19
|
|
|
20
|
+
## 0.4.0 - 2026-09-21
|
|
21
|
+
|
|
22
|
+
### Security
|
|
23
|
+
|
|
24
|
+
Forge queries ignore `GH_REPO` and `GITLAB_REPO`, so a merged request in
|
|
25
|
+
another repository cannot authorize removal here.
|
|
26
|
+
|
|
27
|
+
Printed branch restoration commands and `gwnb` checkout hints quote branch
|
|
28
|
+
names so shell metacharacters are treated as part of the name.
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
|
|
32
|
+
`gws` reports how many worktrees under the shared `.worktrees` directory
|
|
33
|
+
belong to other repositories, with the count in `gws --json` as `neighbours`.
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
|
|
37
|
+
After a failed fetch, worktree assessments use local refs and skip forge
|
|
38
|
+
queries.
|
|
39
|
+
|
|
40
|
+
`gwl` and `gwr` shell completions omit paths containing newlines, which
|
|
41
|
+
cannot fit their one-row-per-line format; those worktrees remain reachable
|
|
42
|
+
by name or path.
|
|
43
|
+
|
|
44
|
+
Pressing Ctrl-C at a worktree selection or removal prompt exits with code
|
|
45
|
+
130 and no traceback. No worktree is selected or removed.
|
|
46
|
+
|
|
47
|
+
## 0.3.1 - 2026-09-20
|
|
48
|
+
|
|
49
|
+
`gws` and `gwp` list the main checkout, and `gwl`'s picker shows the
|
|
50
|
+
worktree you are standing in. Both listings used to leave those rows out, so
|
|
51
|
+
a repository with the main checkout and one worktree showed one row where
|
|
52
|
+
`git worktree list` shows two, which reads as though something went missing
|
|
53
|
+
rather than as where you already are.
|
|
54
|
+
|
|
55
|
+
The main checkout is `keep`, with `it is the main checkout, and never
|
|
56
|
+
removable`. Nothing proposes it, and `git worktree remove` answers
|
|
57
|
+
`fatal: '<path>' is a main working tree` whatever flag it is given, so `gwr`
|
|
58
|
+
still does not offer it.
|
|
59
|
+
|
|
60
|
+
The one you are standing in carries a `*` rather than a number:
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
* cleanup /home/you/git/.worktrees/cleanup/repo
|
|
64
|
+
1 docs-ship-with-the-change (main) /home/you/git/repo
|
|
65
|
+
which? [1-1, or blank to cancel]
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Two things move with those rows. The counts include the main checkout, so a
|
|
69
|
+
repository with one linked worktree reads `1 removable, 1 kept, 0 unclear`
|
|
70
|
+
where it read `1 removable, 0 kept, 0 unclear`, and `gws --json` and
|
|
71
|
+
`gwp --json` carry the extra verdict. A caller filtering on
|
|
72
|
+
`verdict == "remove"` is unaffected; one reading `verdicts[0]` gets the main
|
|
73
|
+
checkout now.
|
|
74
|
+
|
|
75
|
+
`no worktrees besides the main checkout` is on stderr rather than stdout, and
|
|
76
|
+
says `; gwa NAME makes one`. The table is always on stdout now, so stdout is
|
|
77
|
+
never that sentence instead.
|
|
78
|
+
|
|
20
79
|
## 0.3.0 - 2026-09-20
|
|
21
80
|
|
|
22
81
|
`gwl` with no query asks which worktree rather than moving you to one.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: git-worktrees
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Git worktree commands that refuse to lose work.
|
|
5
5
|
Project-URL: Bug reports, https://github.com/MihaiBojin/worktrees/issues/new
|
|
6
6
|
Project-URL: Source, https://github.com/MihaiBojin/worktrees
|
|
@@ -64,6 +64,10 @@ function, because a binary cannot change its caller's directory.
|
|
|
64
64
|
|
|
65
65
|
`worktrees` is the same program under its long name.
|
|
66
66
|
|
|
67
|
+
Ctrl-C interrupts a running command with exit code 130 and no traceback.
|
|
68
|
+
At a selection or removal prompt, it cancels without choosing or removing
|
|
69
|
+
a worktree.
|
|
70
|
+
|
|
67
71
|
`gws` and `gwp` are what this tool is for and their behaviour is settled.
|
|
68
72
|
|
|
69
73
|
**`gwnb` and `gwrot` are alpha and may go.** They start branches rather than
|
|
@@ -160,6 +164,12 @@ subcommand and shorthand, `gwl --complete` prints every worktree, and both
|
|
|
160
164
|
shells narrow what those return, so the matching stays in one place and a
|
|
161
165
|
command added to the table needs no edit in either shell.
|
|
162
166
|
|
|
167
|
+
One row a line, `label<TAB>path`. A worktree whose path holds a newline is
|
|
168
|
+
left out of that listing, because both shells would read it as two rows and
|
|
169
|
+
offer the tail as a worktree of its own. `gwa` cannot make such a path, since
|
|
170
|
+
it derives from a branch name and git refuses a newline in a ref, and the
|
|
171
|
+
worktree is still reachable by name or path.
|
|
172
|
+
|
|
163
173
|
Neither manager puts a binary on `$PATH`, which is why the two installs stay
|
|
164
174
|
separate.
|
|
165
175
|
|
|
@@ -168,19 +178,30 @@ separate.
|
|
|
168
178
|
```console
|
|
169
179
|
$ gws
|
|
170
180
|
VERDICT BRANCH WHY PATH
|
|
181
|
+
keep main it is the main checkout, and never removable /home/you/git/repo
|
|
171
182
|
keep dirty-work it has uncommitted changes /home/you/git/.worktrees/dirty-work/repo
|
|
172
183
|
keep holds-secrets merged, but holds 2 ignored path(s); pass --delete-ignored /home/you/git/.worktrees/holds-secrets/repo
|
|
173
184
|
unknown never-pushed not merged into origin/main, and no upstream says whether its commits were pushed /home/you/git/.worktrees/never-pushed/repo
|
|
174
185
|
remove squash-merged squash-merged /home/you/git/.worktrees/squash-merged/repo
|
|
175
186
|
|
|
176
|
-
1 removable,
|
|
187
|
+
1 removable, 3 kept, 1 unclear
|
|
188
|
+
2 worktree(s) under /home/you/git/.worktrees belong to another repository
|
|
177
189
|
unclear, and gwp does not touch these: never-pushed
|
|
178
190
|
gwp removes the 1 marked removable
|
|
179
191
|
```
|
|
180
192
|
|
|
181
|
-
Rows come in `git worktree list` order
|
|
193
|
+
Rows come in `git worktree list` order, the main checkout first. It is there
|
|
194
|
+
so the table shows what `git worktree list` shows; nothing proposes it, and
|
|
195
|
+
`git worktree remove` answers `fatal: '<path>' is a main working tree`
|
|
196
|
+
whatever flag it is given. Paths are absolute wherever this
|
|
182
197
|
prints one, so a row can be pasted into the next command. The table and the
|
|
183
|
-
count are on stdout;
|
|
198
|
+
count are on stdout; everything after them is on stderr.
|
|
199
|
+
|
|
200
|
+
Every repository in the same parent directory keeps its worktrees under that
|
|
201
|
+
one `.worktrees` root, so some of the directories in there are a sibling's.
|
|
202
|
+
`gws` counts those and says so, because nothing else does, and `--json`
|
|
203
|
+
carries the same count as `neighbours`. No command here reads or removes
|
|
204
|
+
them, and the count comes from walking the root rather than from asking git.
|
|
184
205
|
|
|
185
206
|
On a terminal the verdict carries its own colour, `remove` green, `keep` blue
|
|
186
207
|
and `unknown` yellow, with the branch in bold and the path dimmed. That
|
|
@@ -204,7 +225,13 @@ squashes, so the intermediate state it holds differs from the final one in
|
|
|
204
225
|
the same regions, and a diff cannot separate a stale branch from one with
|
|
205
226
|
work left. A merged pull request settles it, cross-checked against the
|
|
206
227
|
commits an upstream has not got, because a request speaks for what reached
|
|
207
|
-
it and nothing about what never did. `--no-forge` decides from git alone
|
|
228
|
+
it and nothing about what never did. `--no-forge` decides from git alone, and
|
|
229
|
+
so does a run whose fetch just failed.
|
|
230
|
+
|
|
231
|
+
The question goes to the repository the command is standing in and nowhere
|
|
232
|
+
else. `GH_REPO` and `GITLAB_REPO` beat that directory, so both are dropped
|
|
233
|
+
before `gh` or `glab` runs; everything else in the environment, the token
|
|
234
|
+
included, is passed through.
|
|
208
235
|
|
|
209
236
|
A record left behind by a directory somebody deleted by hand is nobody's
|
|
210
237
|
verdict. `gws` names how many there are; clearing them is `git worktree prune`,
|
|
@@ -326,13 +353,18 @@ show me the options, and being moved without being asked is not that. So it
|
|
|
326
353
|
asks, numbered, however many there are:
|
|
327
354
|
|
|
328
355
|
```console
|
|
329
|
-
$ gwl # standing in
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
356
|
+
$ gwl # standing in never-pushed
|
|
357
|
+
* never-pushed /home/you/git/.worktrees/never-pushed/repo
|
|
358
|
+
1 main /home/you/git/repo
|
|
359
|
+
2 dirty-work /home/you/git/.worktrees/dirty-work/repo
|
|
360
|
+
3 holds-secrets /home/you/git/.worktrees/holds-secrets/repo
|
|
333
361
|
which? [1-3, or blank to cancel]
|
|
334
362
|
```
|
|
335
363
|
|
|
364
|
+
The one you are standing in is marked `*` and carries no number. It is where
|
|
365
|
+
you are rather than somewhere to go, and a list without it shows three rows
|
|
366
|
+
where `git worktree list` shows four.
|
|
367
|
+
|
|
336
368
|
Matching is substring first and then subsequence, so `tst` finds `add-tests`,
|
|
337
369
|
and a substring hit always outranks a loose one. Without a terminal `gwl`
|
|
338
370
|
refuses at exit 3 and names `--list` and `--json`.
|
|
@@ -443,7 +475,10 @@ print one thing each and have nothing to be quiet about, takes `--json`, `-q`,
|
|
|
443
475
|
|
|
444
476
|
A remote that cannot be reached is not fatal anywhere. The fetch fails, the
|
|
445
477
|
command says so on stderr, and it answers from the refs already here, which is
|
|
446
|
-
where `--no-fetch` sends it on request.
|
|
478
|
+
where `--no-fetch` sends it on request. The forge is not asked either: it is
|
|
479
|
+
over the same network, and `gh` waits 30 seconds before saying so, once per
|
|
480
|
+
branch. `--no-fetch` alone says nothing about the network, so it leaves the
|
|
481
|
+
forge asked.
|
|
447
482
|
|
|
448
483
|
Data goes to stdout and diagnostics to stderr, the prompt included, so `--json`
|
|
449
484
|
is parseable in every mode. Colour is decided per stream and only for a
|
|
@@ -498,7 +533,9 @@ is refused with them: it deletes refs without `-d` appearing at all.
|
|
|
498
533
|
The Python, the tests and the release procedure are in
|
|
499
534
|
[docs/DEVELOPMENT.md](docs/DEVELOPMENT.md). The rules the code follows are in
|
|
500
535
|
[AGENTS.md](AGENTS.md). What changed in each release is in
|
|
501
|
-
[CHANGELOG.md](CHANGELOG.md).
|
|
536
|
+
[CHANGELOG.md](CHANGELOG.md). What was decided and what must not break,
|
|
537
|
+
including the alternatives that were closed, is in
|
|
538
|
+
[docs/REFERENCE.md](docs/REFERENCE.md).
|
|
502
539
|
|
|
503
540
|
## Licence
|
|
504
541
|
|
|
@@ -38,6 +38,10 @@ function, because a binary cannot change its caller's directory.
|
|
|
38
38
|
|
|
39
39
|
`worktrees` is the same program under its long name.
|
|
40
40
|
|
|
41
|
+
Ctrl-C interrupts a running command with exit code 130 and no traceback.
|
|
42
|
+
At a selection or removal prompt, it cancels without choosing or removing
|
|
43
|
+
a worktree.
|
|
44
|
+
|
|
41
45
|
`gws` and `gwp` are what this tool is for and their behaviour is settled.
|
|
42
46
|
|
|
43
47
|
**`gwnb` and `gwrot` are alpha and may go.** They start branches rather than
|
|
@@ -134,6 +138,12 @@ subcommand and shorthand, `gwl --complete` prints every worktree, and both
|
|
|
134
138
|
shells narrow what those return, so the matching stays in one place and a
|
|
135
139
|
command added to the table needs no edit in either shell.
|
|
136
140
|
|
|
141
|
+
One row a line, `label<TAB>path`. A worktree whose path holds a newline is
|
|
142
|
+
left out of that listing, because both shells would read it as two rows and
|
|
143
|
+
offer the tail as a worktree of its own. `gwa` cannot make such a path, since
|
|
144
|
+
it derives from a branch name and git refuses a newline in a ref, and the
|
|
145
|
+
worktree is still reachable by name or path.
|
|
146
|
+
|
|
137
147
|
Neither manager puts a binary on `$PATH`, which is why the two installs stay
|
|
138
148
|
separate.
|
|
139
149
|
|
|
@@ -142,19 +152,30 @@ separate.
|
|
|
142
152
|
```console
|
|
143
153
|
$ gws
|
|
144
154
|
VERDICT BRANCH WHY PATH
|
|
155
|
+
keep main it is the main checkout, and never removable /home/you/git/repo
|
|
145
156
|
keep dirty-work it has uncommitted changes /home/you/git/.worktrees/dirty-work/repo
|
|
146
157
|
keep holds-secrets merged, but holds 2 ignored path(s); pass --delete-ignored /home/you/git/.worktrees/holds-secrets/repo
|
|
147
158
|
unknown never-pushed not merged into origin/main, and no upstream says whether its commits were pushed /home/you/git/.worktrees/never-pushed/repo
|
|
148
159
|
remove squash-merged squash-merged /home/you/git/.worktrees/squash-merged/repo
|
|
149
160
|
|
|
150
|
-
1 removable,
|
|
161
|
+
1 removable, 3 kept, 1 unclear
|
|
162
|
+
2 worktree(s) under /home/you/git/.worktrees belong to another repository
|
|
151
163
|
unclear, and gwp does not touch these: never-pushed
|
|
152
164
|
gwp removes the 1 marked removable
|
|
153
165
|
```
|
|
154
166
|
|
|
155
|
-
Rows come in `git worktree list` order
|
|
167
|
+
Rows come in `git worktree list` order, the main checkout first. It is there
|
|
168
|
+
so the table shows what `git worktree list` shows; nothing proposes it, and
|
|
169
|
+
`git worktree remove` answers `fatal: '<path>' is a main working tree`
|
|
170
|
+
whatever flag it is given. Paths are absolute wherever this
|
|
156
171
|
prints one, so a row can be pasted into the next command. The table and the
|
|
157
|
-
count are on stdout;
|
|
172
|
+
count are on stdout; everything after them is on stderr.
|
|
173
|
+
|
|
174
|
+
Every repository in the same parent directory keeps its worktrees under that
|
|
175
|
+
one `.worktrees` root, so some of the directories in there are a sibling's.
|
|
176
|
+
`gws` counts those and says so, because nothing else does, and `--json`
|
|
177
|
+
carries the same count as `neighbours`. No command here reads or removes
|
|
178
|
+
them, and the count comes from walking the root rather than from asking git.
|
|
158
179
|
|
|
159
180
|
On a terminal the verdict carries its own colour, `remove` green, `keep` blue
|
|
160
181
|
and `unknown` yellow, with the branch in bold and the path dimmed. That
|
|
@@ -178,7 +199,13 @@ squashes, so the intermediate state it holds differs from the final one in
|
|
|
178
199
|
the same regions, and a diff cannot separate a stale branch from one with
|
|
179
200
|
work left. A merged pull request settles it, cross-checked against the
|
|
180
201
|
commits an upstream has not got, because a request speaks for what reached
|
|
181
|
-
it and nothing about what never did. `--no-forge` decides from git alone
|
|
202
|
+
it and nothing about what never did. `--no-forge` decides from git alone, and
|
|
203
|
+
so does a run whose fetch just failed.
|
|
204
|
+
|
|
205
|
+
The question goes to the repository the command is standing in and nowhere
|
|
206
|
+
else. `GH_REPO` and `GITLAB_REPO` beat that directory, so both are dropped
|
|
207
|
+
before `gh` or `glab` runs; everything else in the environment, the token
|
|
208
|
+
included, is passed through.
|
|
182
209
|
|
|
183
210
|
A record left behind by a directory somebody deleted by hand is nobody's
|
|
184
211
|
verdict. `gws` names how many there are; clearing them is `git worktree prune`,
|
|
@@ -300,13 +327,18 @@ show me the options, and being moved without being asked is not that. So it
|
|
|
300
327
|
asks, numbered, however many there are:
|
|
301
328
|
|
|
302
329
|
```console
|
|
303
|
-
$ gwl # standing in
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
330
|
+
$ gwl # standing in never-pushed
|
|
331
|
+
* never-pushed /home/you/git/.worktrees/never-pushed/repo
|
|
332
|
+
1 main /home/you/git/repo
|
|
333
|
+
2 dirty-work /home/you/git/.worktrees/dirty-work/repo
|
|
334
|
+
3 holds-secrets /home/you/git/.worktrees/holds-secrets/repo
|
|
307
335
|
which? [1-3, or blank to cancel]
|
|
308
336
|
```
|
|
309
337
|
|
|
338
|
+
The one you are standing in is marked `*` and carries no number. It is where
|
|
339
|
+
you are rather than somewhere to go, and a list without it shows three rows
|
|
340
|
+
where `git worktree list` shows four.
|
|
341
|
+
|
|
310
342
|
Matching is substring first and then subsequence, so `tst` finds `add-tests`,
|
|
311
343
|
and a substring hit always outranks a loose one. Without a terminal `gwl`
|
|
312
344
|
refuses at exit 3 and names `--list` and `--json`.
|
|
@@ -417,7 +449,10 @@ print one thing each and have nothing to be quiet about, takes `--json`, `-q`,
|
|
|
417
449
|
|
|
418
450
|
A remote that cannot be reached is not fatal anywhere. The fetch fails, the
|
|
419
451
|
command says so on stderr, and it answers from the refs already here, which is
|
|
420
|
-
where `--no-fetch` sends it on request.
|
|
452
|
+
where `--no-fetch` sends it on request. The forge is not asked either: it is
|
|
453
|
+
over the same network, and `gh` waits 30 seconds before saying so, once per
|
|
454
|
+
branch. `--no-fetch` alone says nothing about the network, so it leaves the
|
|
455
|
+
forge asked.
|
|
421
456
|
|
|
422
457
|
Data goes to stdout and diagnostics to stderr, the prompt included, so `--json`
|
|
423
458
|
is parseable in every mode. Colour is decided per stream and only for a
|
|
@@ -472,7 +507,9 @@ is refused with them: it deletes refs without `-d` appearing at all.
|
|
|
472
507
|
The Python, the tests and the release procedure are in
|
|
473
508
|
[docs/DEVELOPMENT.md](docs/DEVELOPMENT.md). The rules the code follows are in
|
|
474
509
|
[AGENTS.md](AGENTS.md). What changed in each release is in
|
|
475
|
-
[CHANGELOG.md](CHANGELOG.md).
|
|
510
|
+
[CHANGELOG.md](CHANGELOG.md). What was decided and what must not break,
|
|
511
|
+
including the alternatives that were closed, is in
|
|
512
|
+
[docs/REFERENCE.md](docs/REFERENCE.md).
|
|
476
513
|
|
|
477
514
|
## Licence
|
|
478
515
|
|
|
@@ -24,7 +24,9 @@ invisible to it, so CI is the first thing to format a file you just wrote.
|
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
The rules this code follows, and the reasoning behind them, are in
|
|
27
|
-
[AGENTS.md](../AGENTS.md).
|
|
27
|
+
[AGENTS.md](../AGENTS.md). What was decided, what must not break and which
|
|
28
|
+
failure classes have a test are in [REFERENCE.md](REFERENCE.md). This file is
|
|
29
|
+
what to run.
|
|
28
30
|
|
|
29
31
|
## Layout
|
|
30
32
|
|