git-worktrees 0.5.1__tar.gz → 0.6.1__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.6.1/.github/workflows/codeql.yml +48 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/.github/workflows/publish.yml +27 -8
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/.github/workflows/testpypi.yml +1 -1
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/.github/workflows/tests.yml +11 -6
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/.releasetools.yaml +3 -1
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/AGENTS.md +41 -12
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/CHANGELOG.md +71 -0
- git_worktrees-0.6.1/Makefile +9 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/PKG-INFO +123 -47
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/README.md +121 -45
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/completions/gw.fish +1 -1
- git_worktrees-0.6.1/completions/gwbc.fish +13 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/completions/gwbs.fish +2 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/completions/gwrot.fish +1 -1
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/completions/gws.fish +2 -0
- git_worktrees-0.6.1/conf.d/worktrees.fish +7 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/docs/DEVELOPMENT.md +24 -14
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/docs/REFERENCE.md +13 -9
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/hatch_build.py +2 -2
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/pyproject.toml +3 -3
- git_worktrees-0.6.1/scripts/bump_version.py +77 -0
- git_worktrees-0.6.1/src/worktrees/branch_cli.py +311 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/src/worktrees/branches.py +29 -6
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/src/worktrees/cli.py +301 -120
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/src/worktrees/forge.py +10 -7
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/src/worktrees/git.py +17 -5
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/src/worktrees/new_branch.py +8 -3
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/src/worktrees/pick.py +5 -3
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/src/worktrees/prune.py +16 -8
- git_worktrees-0.6.1/src/worktrees/render.py +259 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/src/worktrees/repo.py +68 -3
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/src/worktrees/rotate.py +78 -16
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/src/worktrees/worktree.py +11 -8
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/tests/test_branches.py +34 -1
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/tests/test_cli.py +147 -4
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/tests/test_completions.py +2 -1
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/tests/test_gates.py +1 -1
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/tests/test_new_branch.py +13 -12
- git_worktrees-0.6.1/tests/test_render.py +211 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/tests/test_rotate.py +110 -10
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/tests/test_shims.py +38 -2
- git_worktrees-0.6.1/tests/test_version.py +233 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/uv.lock +1 -1
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/zsh/plugins/worktrees/completions/_gw +1 -0
- git_worktrees-0.5.1/zsh/plugins/worktrees/completions/_gwnb → git_worktrees-0.6.1/zsh/plugins/worktrees/completions/_gwbc +2 -2
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/zsh/plugins/worktrees/completions/_gwbs +2 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/zsh/plugins/worktrees/completions/_gwrot +1 -1
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/zsh/plugins/worktrees/completions/_gws +2 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/zsh/plugins/worktrees/worktrees.plugin.zsh +7 -2
- git_worktrees-0.5.1/completions/gwnb.fish +0 -13
- git_worktrees-0.5.1/conf.d/worktrees.fish +0 -3
- git_worktrees-0.5.1/src/worktrees/branch_cli.py +0 -212
- git_worktrees-0.5.1/src/worktrees/render.py +0 -94
- git_worktrees-0.5.1/tests/test_render.py +0 -75
- git_worktrees-0.5.1/tests/test_version.py +0 -87
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/.claude/settings.json +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/.gitignore +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/.pre-commit-config.yaml +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/.python-version +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/LICENSE +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/completions/gwa.fish +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/completions/gwbd.fish +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/completions/gwh.fish +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/completions/gwl.fish +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/completions/gwm.fish +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/completions/gwp.fish +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/completions/gwr.fish +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/completions/worktrees.fish +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/docs/BENCHMARK.md +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/docs/commands/branch-delete.md +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/docs/commands/branch-status.md +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/functions/gwa.fish +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/functions/gwl.fish +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/functions/gwm.fish +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/functions/gwr!.fish +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/functions/gwr.fish +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/renovate.json +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/scripts/README.md +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/scripts/benchmark.py +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/scripts/verify-publish.bash +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/src/worktrees/__init__.py +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/src/worktrees/branch_forge.py +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/src/worktrees/errors.py +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/src/worktrees/layout.py +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/src/worktrees/merged.py +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/src/worktrees/progress.py +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/src/worktrees/verdicts.py +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/tests/conftest.py +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/tests/test_benchmark.py +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/tests/test_branch_forge.py +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/tests/test_fixture.py +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/tests/test_forge.py +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/tests/test_spec.py +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/tests/test_worktree.py +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/zsh/plugins/worktrees/completions/_gwa +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/zsh/plugins/worktrees/completions/_gwbd +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/zsh/plugins/worktrees/completions/_gwh +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/zsh/plugins/worktrees/completions/_gwl +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/zsh/plugins/worktrees/completions/_gwm +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/zsh/plugins/worktrees/completions/_gwp +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/zsh/plugins/worktrees/completions/_gwr +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/zsh/plugins/worktrees/functions/gwa +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/zsh/plugins/worktrees/functions/gwl +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/zsh/plugins/worktrees/functions/gwm +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/zsh/plugins/worktrees/functions/gwr +0 -0
- {git_worktrees-0.5.1 → git_worktrees-0.6.1}/zsh/plugins/worktrees/functions/gwr! +0 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
name: CodeQL
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
push:
|
|
6
|
+
branches:
|
|
7
|
+
- main
|
|
8
|
+
# New queries reach code nobody has pushed to.
|
|
9
|
+
schedule:
|
|
10
|
+
- cron: "17 4 * * 1"
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
|
|
15
|
+
concurrency:
|
|
16
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
17
|
+
cancel-in-progress: true
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
analyze:
|
|
21
|
+
name: Analyze (${{ matrix.language }}, ${{ matrix.os }})
|
|
22
|
+
runs-on: ${{ matrix.os }}
|
|
23
|
+
permissions:
|
|
24
|
+
contents: read
|
|
25
|
+
security-events: write
|
|
26
|
+
strategy:
|
|
27
|
+
fail-fast: false
|
|
28
|
+
matrix:
|
|
29
|
+
os: [ubuntu-24.04, ubuntu-26.04]
|
|
30
|
+
language: [actions, python]
|
|
31
|
+
steps:
|
|
32
|
+
- name: Checkout code
|
|
33
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
34
|
+
|
|
35
|
+
# Neither language compiles, so build-mode none reads the source as it
|
|
36
|
+
# is and nothing has to be installed first.
|
|
37
|
+
- name: Initialize CodeQL
|
|
38
|
+
uses: github/codeql-action/init@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
|
|
39
|
+
with:
|
|
40
|
+
languages: ${{ matrix.language }}
|
|
41
|
+
build-mode: none
|
|
42
|
+
|
|
43
|
+
# The category carries the runner, so the two uploads for one language
|
|
44
|
+
# are two analyses rather than one replacing the other.
|
|
45
|
+
- name: Analyze
|
|
46
|
+
uses: github/codeql-action/analyze@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
|
|
47
|
+
with:
|
|
48
|
+
category: /language:${{ matrix.language }}/os:${{ matrix.os }}
|
|
@@ -36,7 +36,7 @@ jobs:
|
|
|
36
36
|
# byte-for-byte what was tested and installed here.
|
|
37
37
|
build:
|
|
38
38
|
name: Build
|
|
39
|
-
runs-on: ubuntu-
|
|
39
|
+
runs-on: ubuntu-24.04
|
|
40
40
|
permissions:
|
|
41
41
|
contents: read
|
|
42
42
|
# Reading another workflow's runs. Without it the tests guard below
|
|
@@ -127,7 +127,7 @@ jobs:
|
|
|
127
127
|
|
|
128
128
|
publish:
|
|
129
129
|
name: Publish to PyPI
|
|
130
|
-
runs-on: ubuntu-
|
|
130
|
+
runs-on: ubuntu-24.04
|
|
131
131
|
needs: build
|
|
132
132
|
# Binds this job to the trusted publisher registered for `pypi`. Add a
|
|
133
133
|
# required reviewer on this environment for a manual gate before anything
|
|
@@ -163,8 +163,12 @@ jobs:
|
|
|
163
163
|
# PyPI can take time to serve an accepted upload. Verification runs in a
|
|
164
164
|
# separate job so that delay does not block the GitHub release.
|
|
165
165
|
verify:
|
|
166
|
-
name: Verify PyPI install and attestations
|
|
167
|
-
runs-on:
|
|
166
|
+
name: Verify PyPI install and attestations (${{ matrix.os }})
|
|
167
|
+
runs-on: ${{ matrix.os }}
|
|
168
|
+
strategy:
|
|
169
|
+
fail-fast: false
|
|
170
|
+
matrix:
|
|
171
|
+
os: [ubuntu-24.04, ubuntu-26.04]
|
|
168
172
|
needs: publish
|
|
169
173
|
permissions:
|
|
170
174
|
contents: read
|
|
@@ -188,17 +192,32 @@ jobs:
|
|
|
188
192
|
name: dist
|
|
189
193
|
path: dist/
|
|
190
194
|
|
|
191
|
-
# The install check
|
|
195
|
+
# The install check resolves the wheel alone, so the sdist can still be
|
|
196
|
+
# missing from PyPI here. A file PyPI does not serve yet is asked again,
|
|
197
|
+
# backing off from 15s over eight attempts as the install check does;
|
|
198
|
+
# any other failure ends the job at once.
|
|
192
199
|
- name: Verify attestations on PyPI
|
|
193
200
|
run: |
|
|
194
201
|
for f in dist/*.whl dist/*.tar.gz; do
|
|
195
|
-
|
|
196
|
-
|
|
202
|
+
file="${f#dist/}"
|
|
203
|
+
delay=15
|
|
204
|
+
for attempt in 1 2 3 4 5 6 7 8; do
|
|
205
|
+
code=0
|
|
206
|
+
uvx pypi-attestations@0.0.30 verify pypi \
|
|
207
|
+
--repository "https://github.com/$GITHUB_REPOSITORY" "pypi:$file" 2>err.txt || code=$?
|
|
208
|
+
cat err.txt >&2
|
|
209
|
+
[ "$code" -ne 0 ] || break
|
|
210
|
+
grep -q "Could not find the artifact" err.txt || exit 1
|
|
211
|
+
[ "$attempt" -lt 8 ] || exit 1
|
|
212
|
+
echo "waiting ${delay}s for PyPI to serve $file (attempt $attempt/8)..." >&2
|
|
213
|
+
sleep "$delay"
|
|
214
|
+
delay=$((delay * 2))
|
|
215
|
+
done
|
|
197
216
|
done
|
|
198
217
|
|
|
199
218
|
release:
|
|
200
219
|
name: Release
|
|
201
|
-
runs-on: ubuntu-
|
|
220
|
+
runs-on: ubuntu-24.04
|
|
202
221
|
needs: publish
|
|
203
222
|
permissions:
|
|
204
223
|
contents: write
|
|
@@ -22,8 +22,12 @@ concurrency:
|
|
|
22
22
|
|
|
23
23
|
jobs:
|
|
24
24
|
lint:
|
|
25
|
-
name: Lint
|
|
26
|
-
runs-on:
|
|
25
|
+
name: Lint (${{ matrix.os }})
|
|
26
|
+
runs-on: ${{ matrix.os }}
|
|
27
|
+
strategy:
|
|
28
|
+
fail-fast: false
|
|
29
|
+
matrix:
|
|
30
|
+
os: [ubuntu-24.04, ubuntu-26.04]
|
|
27
31
|
steps:
|
|
28
32
|
- name: Checkout code
|
|
29
33
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
@@ -33,7 +37,7 @@ jobs:
|
|
|
33
37
|
with:
|
|
34
38
|
python-version: "3.14"
|
|
35
39
|
enable-cache: true
|
|
36
|
-
cache-suffix: ${{ github.workflow }}-${{ github.job }}
|
|
40
|
+
cache-suffix: ${{ github.workflow }}-${{ github.job }}-${{ matrix.os }}
|
|
37
41
|
|
|
38
42
|
- name: Install dependencies
|
|
39
43
|
run: uv sync --all-extras --locked
|
|
@@ -44,13 +48,14 @@ jobs:
|
|
|
44
48
|
run: uv run --no-sync pre-commit run --all-files --show-diff-on-failure
|
|
45
49
|
|
|
46
50
|
test:
|
|
47
|
-
name: Python ${{ matrix.python-version }}
|
|
48
|
-
runs-on:
|
|
51
|
+
name: Python ${{ matrix.python-version }} (${{ matrix.os }})
|
|
52
|
+
runs-on: ${{ matrix.os }}
|
|
49
53
|
strategy:
|
|
50
54
|
# One version failing is a fact about that version, so let the others
|
|
51
55
|
# finish and say which.
|
|
52
56
|
fail-fast: false
|
|
53
57
|
matrix:
|
|
58
|
+
os: [ubuntu-24.04, ubuntu-26.04]
|
|
54
59
|
python-version: ["3.11", "3.12", "3.13", "3.14"]
|
|
55
60
|
|
|
56
61
|
steps:
|
|
@@ -67,7 +72,7 @@ jobs:
|
|
|
67
72
|
with:
|
|
68
73
|
python-version: ${{ matrix.python-version }}
|
|
69
74
|
enable-cache: true
|
|
70
|
-
cache-suffix: ${{ github.workflow }}-${{ github.job }}
|
|
75
|
+
cache-suffix: ${{ github.workflow }}-${{ github.job }}-${{ matrix.os }}
|
|
71
76
|
|
|
72
77
|
- name: Install dependencies
|
|
73
78
|
# --locked fails the run on a stale uv.lock, rather than quietly
|
|
@@ -10,7 +10,9 @@ projects:
|
|
|
10
10
|
- path: ./
|
|
11
11
|
manifest: pyproject.toml
|
|
12
12
|
changelog: CHANGELOG.md
|
|
13
|
-
|
|
13
|
+
# `uv version` for pyproject.toml and uv.lock, then the copies the shell
|
|
14
|
+
# plugins and the README's install lines carry.
|
|
15
|
+
bump: python3 scripts/bump_version.py {version}
|
|
14
16
|
|
|
15
17
|
release:
|
|
16
18
|
branch: main
|
|
@@ -40,7 +40,7 @@ function too, so this is the agent path as much as the human one.
|
|
|
40
40
|
|
|
41
41
|
| | changes directory | ships as |
|
|
42
42
|
| --- | --- | --- |
|
|
43
|
-
| `gws`, `gwp`, `gwbs`, `gwbd`, `
|
|
43
|
+
| `gws`, `gwp`, `gwbs`, `gwbd`, `gwbc`, `gwrot`, `gwh` | no | a console script, and nothing else |
|
|
44
44
|
| a command that lands you somewhere | yes | a console script, plus a function of the same name |
|
|
45
45
|
|
|
46
46
|
A binary cannot `cd` its caller. That is the only thing shell code is here for,
|
|
@@ -75,18 +75,18 @@ It calls the `gwr` function rather than `command gwr`, so the caller still
|
|
|
75
75
|
lands where the binary says, and it has no console script of its own.
|
|
76
76
|
`SHORTCUTS` in `tests/test_shims.py` lists them and holds each to one line.
|
|
77
77
|
|
|
78
|
-
## Two commands
|
|
78
|
+
## Two commands start branches
|
|
79
79
|
|
|
80
|
-
`
|
|
81
|
-
`origin rotate` do
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
copied, and a difference between them is a decision somebody has to make
|
|
85
|
-
later. Say so wherever they are documented.
|
|
80
|
+
`gwbc` and `gwrot` start branches, not worktrees, and do the job
|
|
81
|
+
`origin new-branch` and `origin rotate` do. The name format, the
|
|
82
|
+
stem-stripping and the remote-aware collision check are the same in both, so
|
|
83
|
+
a branch either one names is one the other would have named.
|
|
86
84
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
85
|
+
Two divergences are deliberate. `origin` has a single non-zero exit code and
|
|
86
|
+
draws no line between a usage error and a runtime one; this CLI keeps
|
|
87
|
+
argparse's 2 for a usage error. And `gwrot` refuses, at exit 1, a rotation or
|
|
88
|
+
catch-up that would change nothing, where `origin rotate` makes a branch at
|
|
89
|
+
the same commit under a new name.
|
|
90
90
|
|
|
91
91
|
## Where shell code goes
|
|
92
92
|
|
|
@@ -105,6 +105,14 @@ zsh/plugins/worktrees/completions/_gwa
|
|
|
105
105
|
Neither manager puts a binary on `$PATH`. The console scripts arrive through
|
|
106
106
|
`uv tool install` from the published package, which is a separate step.
|
|
107
107
|
|
|
108
|
+
Both plugins export `WORKTREES_PLUGIN_VERSION`, the release they came from:
|
|
109
|
+
`conf.d/worktrees.fish` and `worktrees.plugin.zsh`, one assignment each.
|
|
110
|
+
`gwh` and `gw version` compare it with `__version__`, in Python; the shell
|
|
111
|
+
files hold the value and no logic. Nothing built can stamp a file a plugin
|
|
112
|
+
manager copies from git, so `scripts/bump_version.py` writes it at release,
|
|
113
|
+
along with the tag in the README's install lines, and `tests/test_version.py`
|
|
114
|
+
fails when a copy disagrees with `pyproject.toml`.
|
|
115
|
+
|
|
108
116
|
Nothing installs this from a checkout on the user's disk. It is consumed as a
|
|
109
117
|
third-party plugin and a third-party tool, so anything that assumes a local
|
|
110
118
|
clone at a known path is wrong here.
|
|
@@ -240,12 +248,33 @@ on a terminal: both are what a script reads. The colour is applied at the
|
|
|
240
248
|
call site that formats a table, and neither path passes a code to one.
|
|
241
249
|
|
|
242
250
|
`progress.py` draws a spinner on stderr and one line saying what is being
|
|
243
|
-
checked, while `gws`, `gwp` and `
|
|
251
|
+
checked, while `gws`, `gwp`, `gwr`, `gwbs` and `gwbd` fetch and judge. It runs only when
|
|
244
252
|
stderr is a terminal that can clear a line, and never under `-q` or `-v`,
|
|
245
253
|
since the verbose log writes to the line it redraws. Anything else printed on
|
|
246
254
|
stderr while it spins goes through `progress.line`, which clears the spinner
|
|
247
255
|
first.
|
|
248
256
|
|
|
257
|
+
Every message on stderr goes through `render.fail`, `render.warn` or
|
|
258
|
+
`render.note`, a usage error and a cancelled picker included. On a terminal
|
|
259
|
+
each leads with its symbol, `✗`, `!` or `→`, and its first line makes flags
|
|
260
|
+
and quoted commands bold, paths dim and shas yellow. A path is a word that
|
|
261
|
+
starts with `/`, `~/`, `./` or `../`, taken whole, so a directory named `-x`
|
|
262
|
+
is not a flag and a uuid inside one is not a sha. A failure prints every line
|
|
263
|
+
red; a warning or a note dims the lines after its first.
|
|
264
|
+
|
|
265
|
+
A branch name is wrapped in `render.branch` and a ref such as `origin/main` in
|
|
266
|
+
`render.ref` where the message is built, since no pattern tells a branch from
|
|
267
|
+
prose; the passes after leave those alone. A branch is bold magenta wherever
|
|
268
|
+
it prints: a table, the picker, a message, a result line. A prompt is
|
|
269
|
+
`render.ask`, the question bold and the answers it takes dim. The line that
|
|
270
|
+
puts a branch back is `render.restore`, painted the way a table paints a
|
|
271
|
+
branch and a sha, and it pastes the same. Off a terminal it is the words
|
|
272
|
+
alone, so a test or a log reads what the code wrote. `-v` prints each command once it has run, as
|
|
273
|
+
`render.trace` lays it out: the line that pastes back, what it printed,
|
|
274
|
+
indented, its exit code when that is not 0 or is the only answer, then a
|
|
275
|
+
blank line. Printing after the run keeps a command and its answer together
|
|
276
|
+
when eight threads are asking at once.
|
|
277
|
+
|
|
249
278
|
## A recent fetch, and a forge answer that cannot change, are reused
|
|
250
279
|
|
|
251
280
|
The README's "What is reused, and for how long" table lists every case and
|
|
@@ -17,6 +17,77 @@ 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.6.1 - 2026-11-02
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
|
|
24
|
+
`gwh` says which release the shell plugin in this shell came from, and whether
|
|
25
|
+
it matches the commands. When the plugin is older, it names the tag to pin it
|
|
26
|
+
to, and when newer, it gives the `uv tool upgrade git-worktrees` to run.
|
|
27
|
+
`gw version` says the same on stderr, and its stdout is still the version
|
|
28
|
+
alone. Both plugins export `WORKTREES_PLUGIN_VERSION` for this. A shell whose
|
|
29
|
+
plugin predates this release reports none.
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
|
|
33
|
+
The README installs the plugins at the release's tag, `fisher install
|
|
34
|
+
MihaiBojin/worktrees@v0.6.1` for fish and `branch:v0.6.1` for Antidote, and
|
|
35
|
+
says how to move each to another release. Moving an existing install onto a
|
|
36
|
+
tag takes an edit to `fish_plugins` and `fisher update`, or `antidote purge
|
|
37
|
+
MihaiBojin/worktrees` before editing the tag.
|
|
38
|
+
|
|
39
|
+
## 0.6.0 - 2026-11-02
|
|
40
|
+
|
|
41
|
+
### Changed
|
|
42
|
+
|
|
43
|
+
`gwnb` is now `gwbc`, and `gw new-branch` is now `gw branch create`. Update
|
|
44
|
+
the fish or zsh plugin so the new name completes. `gwbc` and `gwrot` are no
|
|
45
|
+
longer marked alpha.
|
|
46
|
+
|
|
47
|
+
`gwrot` prints the branch it left and the one it is on now, each with its
|
|
48
|
+
commit, and exits 1 when a rotation or catch-up would change nothing.
|
|
49
|
+
|
|
50
|
+
On a terminal, every command colours its output the same way: errors red
|
|
51
|
+
behind ✗, warnings behind !, notes behind →, branches bold magenta, refs
|
|
52
|
+
blue, commits yellow, paths dim, and each verdict in one colour wherever it
|
|
53
|
+
appears. Piped or redirected output, and any run with `NO_COLOR` set, stays
|
|
54
|
+
plain.
|
|
55
|
+
|
|
56
|
+
`gwl`, `gws`, `gwp` and `gwr` list the main checkout first, then the other
|
|
57
|
+
worktrees from oldest to newest.
|
|
58
|
+
|
|
59
|
+
`-v` prints each git and `gh` command after it runs, with what it printed and
|
|
60
|
+
its exit code indented beneath it.
|
|
61
|
+
|
|
62
|
+
`gwp` names the worktrees it removed.
|
|
63
|
+
|
|
64
|
+
### Added
|
|
65
|
+
|
|
66
|
+
`gws` and `gwbs` take `--only VERDICT`, repeatable, to show only the rows
|
|
67
|
+
marked `remove`, `keep` or `unknown`, in the table and in `--json`. The counts
|
|
68
|
+
under the table still cover every row. Both also take `-f` for
|
|
69
|
+
`--force-refresh`.
|
|
70
|
+
|
|
71
|
+
`gwrot -f` is short for `gwrot --force-refresh`.
|
|
72
|
+
|
|
73
|
+
`gwbd` shows each branch's verdict in its selector and in the list it prints
|
|
74
|
+
before asking, and a `--dry-run` ends by saying how many branches would go.
|
|
75
|
+
|
|
76
|
+
`gwbs` and `gwbd` show a spinner on stderr while they judge, with a line
|
|
77
|
+
naming the branch, the check in progress and how far through the list they
|
|
78
|
+
are, such as `fix-parser: was it squash-merged into main? (4 of 18)`. `gwbd`
|
|
79
|
+
keeps it running while it rechecks each branch before deleting it. It stays
|
|
80
|
+
off when stderr is not a terminal, on `TERM=dumb`, and under `-q` or `-v`.
|
|
81
|
+
|
|
82
|
+
`gwl` names each remote above the picker as host and path, such as
|
|
83
|
+
`origin: github.com/org/repo`, for SSH and HTTPS remotes alike and without
|
|
84
|
+
any user name or token the URL carries.
|
|
85
|
+
|
|
86
|
+
### Fixed
|
|
87
|
+
|
|
88
|
+
`gwbd` says why it kept each branch it was asked to delete, rather than
|
|
89
|
+
exiting 3 with nothing printed.
|
|
90
|
+
|
|
20
91
|
## 0.5.1 - 2026-09-29
|
|
21
92
|
|
|
22
93
|
### Added
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
.PHONY: local-install reset
|
|
2
|
+
|
|
3
|
+
# The working copy, in place of anything published.
|
|
4
|
+
local-install:
|
|
5
|
+
uv tool install --force --from . git-worktrees
|
|
6
|
+
|
|
7
|
+
# Undoes local-install: the latest release from PyPI, and only its commands.
|
|
8
|
+
reset:
|
|
9
|
+
uv tool install --force git-worktrees
|