@gw-tools/gw 0.2.0 → 0.6.1
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.
- package/README.md +595 -47
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,22 +2,87 @@
|
|
|
2
2
|
|
|
3
3
|
A command-line tool for managing git worktrees, built with Deno.
|
|
4
4
|
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [gw - Git Worktree Tools](#gw---git-worktree-tools)
|
|
8
|
+
- [Table of Contents](#table-of-contents)
|
|
9
|
+
- [Quick Start](#quick-start)
|
|
10
|
+
- [Features](#features)
|
|
11
|
+
- [Installation](#installation)
|
|
12
|
+
- [Via npm (Recommended)](#via-npm-recommended)
|
|
13
|
+
- [Build from source](#build-from-source)
|
|
14
|
+
- [Configuration](#configuration)
|
|
15
|
+
- [Auto-Detection](#auto-detection)
|
|
16
|
+
- [Example Configuration](#example-configuration)
|
|
17
|
+
- [Configuration Options](#configuration-options)
|
|
18
|
+
- [Commands](#commands)
|
|
19
|
+
- [add](#add)
|
|
20
|
+
- [Arguments](#arguments)
|
|
21
|
+
- [Options](#options)
|
|
22
|
+
- [Examples](#examples)
|
|
23
|
+
- [Auto-Copy Configuration](#auto-copy-configuration)
|
|
24
|
+
- [root](#root)
|
|
25
|
+
- [Examples](#examples-1)
|
|
26
|
+
- [How It Works](#how-it-works)
|
|
27
|
+
- [init](#init)
|
|
28
|
+
- [Options](#options-1)
|
|
29
|
+
- [Examples](#examples-2)
|
|
30
|
+
- [When to Use](#when-to-use)
|
|
31
|
+
- [sync](#sync)
|
|
32
|
+
- [Arguments](#arguments-1)
|
|
33
|
+
- [Options](#options-2)
|
|
34
|
+
- [Examples](#examples-3)
|
|
35
|
+
- [Git Worktree Proxy Commands](#git-worktree-proxy-commands)
|
|
36
|
+
- [list (ls)](#list-ls)
|
|
37
|
+
- [remove (rm)](#remove-rm)
|
|
38
|
+
- [move (mv)](#move-mv)
|
|
39
|
+
- [prune](#prune)
|
|
40
|
+
- [lock](#lock)
|
|
41
|
+
- [unlock](#unlock)
|
|
42
|
+
- [repair](#repair)
|
|
43
|
+
- [Use Case](#use-case)
|
|
44
|
+
- [Typical Workflow](#typical-workflow)
|
|
45
|
+
- [Development](#development)
|
|
46
|
+
- [Local Development \& Testing](#local-development--testing)
|
|
47
|
+
- [Method 1: Shell Alias (Recommended for Active Development)](#method-1-shell-alias-recommended-for-active-development)
|
|
48
|
+
- [Method 2: Symlink to Compiled Binary (Faster Execution)](#method-2-symlink-to-compiled-binary-faster-execution)
|
|
49
|
+
- [Method 3: Development Wrapper Script (Best of Both Worlds)](#method-3-development-wrapper-script-best-of-both-worlds)
|
|
50
|
+
- [Method 4: npm link (For Testing Installation)](#method-4-npm-link-for-testing-installation)
|
|
51
|
+
- [Watch Mode for Active Development](#watch-mode-for-active-development)
|
|
52
|
+
- [Available Scripts](#available-scripts)
|
|
53
|
+
- [Publishing](#publishing)
|
|
54
|
+
- [Automated Release (Recommended)](#automated-release-recommended)
|
|
55
|
+
- [Manual Publishing](#manual-publishing)
|
|
56
|
+
- [Publishing to JSR (Optional)](#publishing-to-jsr-optional)
|
|
57
|
+
- [Version Management](#version-management)
|
|
58
|
+
- [Project Structure](#project-structure)
|
|
59
|
+
- [Adding New Commands](#adding-new-commands)
|
|
60
|
+
- [License](#license)
|
|
61
|
+
|
|
5
62
|
## Quick Start
|
|
6
63
|
|
|
7
64
|
```bash
|
|
8
65
|
# Install
|
|
9
66
|
npm install -g @gw-tools/gw
|
|
10
67
|
|
|
11
|
-
# Create a new worktree
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
# Copy secrets from main to the new worktree
|
|
15
|
-
gw copy feat-new-feature .env
|
|
68
|
+
# Create a new worktree and copy files
|
|
69
|
+
gw add feat-new-feature .env secrets/
|
|
16
70
|
|
|
17
|
-
# Done! Your new worktree has
|
|
71
|
+
# Done! Your new worktree has the files it needs
|
|
18
72
|
cd feat-new-feature
|
|
19
73
|
```
|
|
20
74
|
|
|
75
|
+
**Or with auto-copy (one-time setup):**
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# Configure auto-copy files once per repository
|
|
79
|
+
gw init --root $(gw root) --auto-copy-files .env,secrets/
|
|
80
|
+
|
|
81
|
+
# Now just create worktrees - files are copied automatically
|
|
82
|
+
gw add feat-another-feature
|
|
83
|
+
cd feat-another-feature
|
|
84
|
+
```
|
|
85
|
+
|
|
21
86
|
## Features
|
|
22
87
|
|
|
23
88
|
- **Copy files between worktrees**: Easily copy secrets, environment files, and configurations from one worktree to another
|
|
@@ -63,65 +128,478 @@ cp dist/packages/gw-tool/gw /usr/local/bin/gw
|
|
|
63
128
|
|
|
64
129
|
## Configuration
|
|
65
130
|
|
|
66
|
-
On first run, `gw` will automatically create a configuration file at
|
|
131
|
+
On first run, `gw` will automatically detect your git repository root and create a configuration file at `.gw/config.json`. The tool finds the config by walking up the directory tree from your current location, so you can run `gw` commands from anywhere within your repository.
|
|
132
|
+
|
|
133
|
+
### Auto-Detection
|
|
134
|
+
|
|
135
|
+
The tool automatically:
|
|
136
|
+
|
|
137
|
+
1. **Searches for existing config**: Walks up from your current directory looking for `.gw/config.json`
|
|
138
|
+
2. **Auto-detects git root**: If no config is found, detects the repository root automatically
|
|
139
|
+
3. **Creates config**: Saves the detected root and default settings to `.gw/config.json`
|
|
140
|
+
|
|
141
|
+
If auto-detection fails (rare edge cases), you can manually initialize:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
gw init --root /path/to/your/repo.git
|
|
145
|
+
```
|
|
67
146
|
|
|
68
147
|
### Example Configuration
|
|
69
148
|
|
|
70
149
|
```json
|
|
71
150
|
{
|
|
72
|
-
"
|
|
151
|
+
"root": "/Users/username/Workspace/my-project.git",
|
|
152
|
+
"defaultBranch": "main",
|
|
153
|
+
"autoCopyFiles": [
|
|
154
|
+
".env",
|
|
155
|
+
"components/agents/.env",
|
|
156
|
+
"components/ui/.vercel/"
|
|
157
|
+
]
|
|
73
158
|
}
|
|
74
159
|
```
|
|
75
160
|
|
|
76
161
|
### Configuration Options
|
|
77
162
|
|
|
78
|
-
- **
|
|
163
|
+
- **root**: Absolute path to the git repository root (automatically detected or manually set with `gw init`)
|
|
164
|
+
- **defaultBranch**: Default source worktree name (optional, defaults to "main")
|
|
165
|
+
- **autoCopyFiles**: Array of file/directory paths to automatically copy when creating worktrees with `gw add` (optional, only set via `gw init --auto-copy-files`)
|
|
79
166
|
|
|
80
167
|
## Commands
|
|
81
168
|
|
|
82
|
-
###
|
|
169
|
+
### add
|
|
170
|
+
|
|
171
|
+
Create a new git worktree with optional automatic file copying.
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
gw add <worktree-name> [files...]
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
This command wraps `git worktree add` and optionally copies files to the new worktree. If `autoCopyFiles` is configured, those files are automatically copied. You can override this by specifying files as arguments.
|
|
178
|
+
|
|
179
|
+
#### Arguments
|
|
180
|
+
|
|
181
|
+
- `<worktree-name>`: Name or path for the new worktree
|
|
182
|
+
- `[files...]`: Optional files to copy (overrides `autoCopyFiles` config)
|
|
183
|
+
|
|
184
|
+
#### Options
|
|
185
|
+
|
|
186
|
+
All `git worktree add` options are supported:
|
|
187
|
+
- `-b <branch>`: Create a new branch
|
|
188
|
+
- `-B <branch>`: Create or reset a branch
|
|
189
|
+
- `--detach`: Detach HEAD in new worktree
|
|
190
|
+
- `--force, -f`: Force checkout even if already checked out
|
|
191
|
+
- `--track`: Track branch from remote
|
|
192
|
+
- `-h, --help`: Show help message
|
|
193
|
+
|
|
194
|
+
#### Examples
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
# Create worktree (auto-copies files if autoCopyFiles is configured)
|
|
198
|
+
gw add feat/new-feature
|
|
199
|
+
|
|
200
|
+
# Create worktree with new branch
|
|
201
|
+
gw add feat/new-feature -b my-branch
|
|
202
|
+
|
|
203
|
+
# Create worktree and copy specific files (overrides config)
|
|
204
|
+
gw add feat/new-feature .env secrets/
|
|
205
|
+
|
|
206
|
+
# Force create even if branch exists elsewhere
|
|
207
|
+
gw add feat/bugfix -f
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
#### Auto-Copy Configuration
|
|
211
|
+
|
|
212
|
+
To enable automatic file copying, configure `autoCopyFiles` using `gw init`:
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
gw init --root /path/to/repo.git --auto-copy-files .env,secrets/,components/ui/.vercel/
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
This creates:
|
|
219
|
+
```json
|
|
220
|
+
{
|
|
221
|
+
"root": "/path/to/repo.git",
|
|
222
|
+
"defaultBranch": "main",
|
|
223
|
+
"autoCopyFiles": [".env", "secrets/", "components/ui/.vercel/"]
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
Now every time you run `gw add`, these files will be automatically copied from your default source worktree (usually `main`) to the new worktree.
|
|
228
|
+
|
|
229
|
+
### root
|
|
230
|
+
|
|
231
|
+
Get the root directory of the current git repository. For git worktrees, returns the parent directory containing all worktrees.
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
gw root
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
This command is useful when working with git worktrees to find the main repository directory that contains all worktrees, regardless of how deeply nested you are in the directory structure.
|
|
238
|
+
|
|
239
|
+
#### Examples
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
# Get repository root path
|
|
243
|
+
gw root
|
|
244
|
+
# Output: /Users/username/Workspace/my-project.git
|
|
245
|
+
|
|
246
|
+
# Navigate to repository root
|
|
247
|
+
cd "$(gw root)"
|
|
248
|
+
|
|
249
|
+
# List all worktrees
|
|
250
|
+
ls "$(gw root)"
|
|
251
|
+
|
|
252
|
+
# Use in scripts
|
|
253
|
+
REPO_ROOT=$(gw root)
|
|
254
|
+
echo "Repository is at: $REPO_ROOT"
|
|
255
|
+
|
|
256
|
+
# Works from any depth
|
|
257
|
+
cd /Users/username/Workspace/my-project.git/feat/deeply/nested/folder
|
|
258
|
+
gw root
|
|
259
|
+
# Output: /Users/username/Workspace/my-project.git
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
#### How It Works
|
|
263
|
+
|
|
264
|
+
- **In a worktree**: Returns the parent directory containing all worktrees (e.g., `/path/to/repo.git`)
|
|
265
|
+
- **In a regular repo**: Returns the directory containing the `.git` directory
|
|
266
|
+
- **From nested directories**: Walks up the directory tree to find the repository root
|
|
267
|
+
|
|
268
|
+
### init
|
|
269
|
+
|
|
270
|
+
Initialize gw configuration for a git repository. This command is only needed if auto-detection fails or if you want to manually specify the repository root.
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
gw init --root <path> [options]
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
#### Options
|
|
277
|
+
|
|
278
|
+
- `--root <path>`: Specify the git repository root path (required)
|
|
279
|
+
- `--default-source <name>`: Set the default source worktree (default: "main")
|
|
280
|
+
- `--auto-copy-files <files>`: Comma-separated list of files to auto-copy when creating worktrees with `gw add`
|
|
281
|
+
- `-h, --help`: Show help message
|
|
282
|
+
|
|
283
|
+
#### Examples
|
|
284
|
+
|
|
285
|
+
```bash
|
|
286
|
+
# Initialize with repository root
|
|
287
|
+
gw init --root /Users/username/Workspace/my-project.git
|
|
288
|
+
|
|
289
|
+
# Initialize with custom default source
|
|
290
|
+
gw init --root /Users/username/Workspace/my-project.git --default-source master
|
|
291
|
+
|
|
292
|
+
# Initialize with auto-copy files
|
|
293
|
+
gw init --root /Users/username/Workspace/my-project.git --auto-copy-files .env,secrets/,components/ui/.vercel/
|
|
294
|
+
|
|
295
|
+
# Show help
|
|
296
|
+
gw init --help
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
#### When to Use
|
|
300
|
+
|
|
301
|
+
In most cases, you won't need to run `gw init` manually because the tool auto-detects your repository root on first run. However, you may need it when:
|
|
302
|
+
|
|
303
|
+
- Auto-detection fails (rare edge cases with non-standard repository structures)
|
|
304
|
+
- You want to override the auto-detected root
|
|
305
|
+
- You're setting up configuration before the repository has standard git structures
|
|
83
306
|
|
|
84
|
-
|
|
307
|
+
The config file is created at `.gw/config.json` in your current directory, so you can run this command from wherever makes sense for your workflow (typically the repository root).
|
|
308
|
+
|
|
309
|
+
### sync
|
|
310
|
+
|
|
311
|
+
Sync files and directories between worktrees, preserving directory structure.
|
|
85
312
|
|
|
86
313
|
```bash
|
|
87
|
-
gw
|
|
314
|
+
gw sync [options] <target-worktree> <files...>
|
|
88
315
|
```
|
|
89
316
|
|
|
90
317
|
#### Arguments
|
|
91
318
|
|
|
92
319
|
- `<target-worktree>`: Name or full path of the target worktree
|
|
93
|
-
- `<files...>`: One or more files or directories to
|
|
320
|
+
- `<files...>`: One or more files or directories to sync (paths relative to worktree root)
|
|
94
321
|
|
|
95
322
|
#### Options
|
|
96
323
|
|
|
97
324
|
- `--from <source>`: Source worktree name (default: from config or "main")
|
|
98
|
-
- `-n, --dry-run`: Show what would be
|
|
325
|
+
- `-n, --dry-run`: Show what would be synced without actually syncing
|
|
99
326
|
- `-h, --help`: Show help message
|
|
100
327
|
|
|
101
328
|
#### Examples
|
|
102
329
|
|
|
103
330
|
```bash
|
|
104
|
-
#
|
|
105
|
-
gw
|
|
331
|
+
# Sync .env file from main to feat-branch
|
|
332
|
+
gw sync feat-branch .env
|
|
106
333
|
|
|
107
|
-
#
|
|
108
|
-
gw
|
|
334
|
+
# Sync multiple files
|
|
335
|
+
gw sync feat-branch .env components/agents/.env components/agents/agents.yaml
|
|
109
336
|
|
|
110
|
-
#
|
|
111
|
-
gw
|
|
337
|
+
# Sync entire directory
|
|
338
|
+
gw sync feat-branch components/ui/.vercel
|
|
112
339
|
|
|
113
340
|
# Use custom source worktree
|
|
114
|
-
gw
|
|
341
|
+
gw sync --from develop feat-branch .env
|
|
115
342
|
|
|
116
343
|
# Dry run to preview changes
|
|
117
|
-
gw
|
|
344
|
+
gw sync --dry-run feat-branch .env
|
|
118
345
|
|
|
119
346
|
# Use absolute path as target
|
|
120
|
-
gw
|
|
347
|
+
gw sync /full/path/to/repo/feat-branch .env
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
### Git Worktree Proxy Commands
|
|
351
|
+
|
|
352
|
+
These commands wrap native `git worktree` operations, providing consistent colored output and help messages. All git flags and options are passed through transparently.
|
|
353
|
+
|
|
354
|
+
#### list (ls)
|
|
355
|
+
|
|
356
|
+
List all worktrees in the repository.
|
|
357
|
+
|
|
358
|
+
```bash
|
|
359
|
+
gw list
|
|
360
|
+
# or
|
|
361
|
+
gw ls
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
**Examples:**
|
|
365
|
+
```bash
|
|
366
|
+
gw list # List all worktrees
|
|
367
|
+
gw list --porcelain # Machine-readable output
|
|
368
|
+
gw list -v # Verbose output
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
#### remove (rm)
|
|
372
|
+
|
|
373
|
+
Remove a worktree from the repository.
|
|
374
|
+
|
|
375
|
+
```bash
|
|
376
|
+
gw remove <worktree>
|
|
377
|
+
# or
|
|
378
|
+
gw rm <worktree>
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
**Examples:**
|
|
382
|
+
```bash
|
|
383
|
+
gw remove feat-branch # Remove a worktree
|
|
384
|
+
gw remove --force feat-branch # Force remove even if dirty
|
|
385
|
+
gw rm feat-branch # Using alias
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
#### move (mv)
|
|
389
|
+
|
|
390
|
+
Move a worktree to a new location.
|
|
391
|
+
|
|
392
|
+
```bash
|
|
393
|
+
gw move <worktree> <new-path>
|
|
394
|
+
# or
|
|
395
|
+
gw mv <worktree> <new-path>
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
**Examples:**
|
|
399
|
+
```bash
|
|
400
|
+
gw move feat-branch ../new-location
|
|
401
|
+
gw mv feat-branch ../new-location
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
#### prune
|
|
405
|
+
|
|
406
|
+
Clean up worktree information for deleted worktrees.
|
|
407
|
+
|
|
408
|
+
```bash
|
|
409
|
+
gw prune
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
**Examples:**
|
|
413
|
+
```bash
|
|
414
|
+
gw prune # Clean up stale worktree information
|
|
415
|
+
gw prune --dry-run # Preview what would be pruned
|
|
416
|
+
gw prune --verbose # Show detailed output
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
#### lock
|
|
420
|
+
|
|
421
|
+
Lock a worktree to prevent removal.
|
|
422
|
+
|
|
423
|
+
```bash
|
|
424
|
+
gw lock <worktree>
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
**Examples:**
|
|
428
|
+
```bash
|
|
429
|
+
gw lock feat-branch
|
|
430
|
+
gw lock --reason "Work in progress" feat-branch
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
#### unlock
|
|
434
|
+
|
|
435
|
+
Unlock a worktree to allow removal.
|
|
436
|
+
|
|
437
|
+
```bash
|
|
438
|
+
gw unlock <worktree>
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
**Examples:**
|
|
442
|
+
```bash
|
|
443
|
+
gw unlock feat-branch
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
#### repair
|
|
447
|
+
|
|
448
|
+
Repair worktree administrative files.
|
|
449
|
+
|
|
450
|
+
```bash
|
|
451
|
+
gw repair [<path>]
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
**Examples:**
|
|
455
|
+
```bash
|
|
456
|
+
gw repair # Repair all worktrees
|
|
457
|
+
gw repair /path/to/worktree # Repair specific worktree
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
## Use Case
|
|
461
|
+
|
|
462
|
+
This tool was originally created to simplify the workflow of copying secrets and environment files when creating new git worktrees. When you create a new worktree for a feature branch, you often need to copy `.env` files, credentials, and other configuration files from your main worktree to the new one. This tool automates that process.
|
|
463
|
+
|
|
464
|
+
The tool automatically detects which git repository you're working in and creates a local config file (`.gw/config.json`) on first use. The config stores the repository root and other settings, so subsequent runs are fast and don't need to re-detect the repository structure. Each repository has its own configuration, and you can customize the default source worktree per repository.
|
|
465
|
+
|
|
466
|
+
### Typical Workflow
|
|
467
|
+
|
|
468
|
+
```bash
|
|
469
|
+
# One-time setup: Configure auto-copy files
|
|
470
|
+
gw init --root $(gw root) --auto-copy-files .env,components/agents/.env,components/ui/.vercel/
|
|
471
|
+
|
|
472
|
+
# From within any worktree of your repository
|
|
473
|
+
# Create a new worktree with auto-copy
|
|
474
|
+
gw add feat-new-feature
|
|
475
|
+
|
|
476
|
+
# Done! Files are automatically copied
|
|
477
|
+
cd feat-new-feature
|
|
478
|
+
|
|
479
|
+
# Alternative: Create worktree and copy specific files
|
|
480
|
+
gw add feat-bugfix .env custom-config.json
|
|
481
|
+
|
|
482
|
+
# Alternative: Use the manual sync command
|
|
483
|
+
git worktree add feat-manual
|
|
484
|
+
gw sync feat-manual .env
|
|
121
485
|
```
|
|
122
486
|
|
|
123
487
|
## Development
|
|
124
488
|
|
|
489
|
+
### Local Development & Testing
|
|
490
|
+
|
|
491
|
+
When developing the tool, you can test changes locally without publishing by creating a global symlink. This allows you to use the `gw` command with live code updates.
|
|
492
|
+
|
|
493
|
+
#### Method 1: Shell Alias (Recommended for Active Development)
|
|
494
|
+
|
|
495
|
+
Create a shell alias that runs the Deno version directly with watch mode:
|
|
496
|
+
|
|
497
|
+
```bash
|
|
498
|
+
# Add to your ~/.zshrc or ~/.bashrc
|
|
499
|
+
alias gw-dev='deno run --allow-all ~/path/to/gw-tools/packages/gw-tool/src/main.ts'
|
|
500
|
+
|
|
501
|
+
# Reload your shell
|
|
502
|
+
source ~/.zshrc # or ~/.bashrc
|
|
503
|
+
|
|
504
|
+
# Now you can use it anywhere
|
|
505
|
+
cd ~/some-project
|
|
506
|
+
gw-dev copy feat-branch .env
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
This gives you instant feedback - just edit the TypeScript files and run the command again.
|
|
510
|
+
|
|
511
|
+
#### Method 2: Symlink to Compiled Binary (Faster Execution)
|
|
512
|
+
|
|
513
|
+
Create a symlink to the compiled binary and recompile when needed:
|
|
514
|
+
|
|
515
|
+
```bash
|
|
516
|
+
# From the workspace root
|
|
517
|
+
nx run gw-tool:compile
|
|
518
|
+
|
|
519
|
+
# Create global symlink (one-time setup)
|
|
520
|
+
sudo ln -sf ~/path/to/gw-tools/dist/packages/gw-tool/gw /usr/local/bin/gw
|
|
521
|
+
|
|
522
|
+
# Now you can use `gw` globally
|
|
523
|
+
cd ~/some-project
|
|
524
|
+
gw sync feat-branch .env
|
|
525
|
+
|
|
526
|
+
# When you make changes, recompile
|
|
527
|
+
nx run gw-tool:compile
|
|
528
|
+
# The symlink automatically points to the new binary
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
#### Method 3: Development Wrapper Script (Best of Both Worlds)
|
|
532
|
+
|
|
533
|
+
Create a wrapper script that provides both speed and live updates:
|
|
534
|
+
|
|
535
|
+
```bash
|
|
536
|
+
# Create ~/bin/gw (make sure ~/bin is in your PATH)
|
|
537
|
+
cat > ~/bin/gw << 'EOF'
|
|
538
|
+
#!/bin/bash
|
|
539
|
+
# Check if we're in development mode (set GW_DEV=1 to use source)
|
|
540
|
+
if [ "$GW_DEV" = "1" ]; then
|
|
541
|
+
exec deno run --allow-all ~/path/to/gw-tools/packages/gw-tool/src/main.ts "$@"
|
|
542
|
+
else
|
|
543
|
+
exec ~/path/to/gw-tools/dist/packages/gw-tool/gw "$@"
|
|
544
|
+
fi
|
|
545
|
+
EOF
|
|
546
|
+
|
|
547
|
+
chmod +x ~/bin/gw
|
|
548
|
+
|
|
549
|
+
# Use compiled version (fast)
|
|
550
|
+
gw sync feat-branch .env
|
|
551
|
+
|
|
552
|
+
# Use development version with live updates
|
|
553
|
+
GW_DEV=1 gw sync feat-branch .env
|
|
554
|
+
|
|
555
|
+
# Or set it for your entire session
|
|
556
|
+
export GW_DEV=1
|
|
557
|
+
gw sync feat-branch .env
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
#### Method 4: npm link (For Testing Installation)
|
|
561
|
+
|
|
562
|
+
Test the npm package installation flow locally:
|
|
563
|
+
|
|
564
|
+
```bash
|
|
565
|
+
# Compile binaries
|
|
566
|
+
nx run gw-tool:compile-all
|
|
567
|
+
|
|
568
|
+
# Prepare npm package
|
|
569
|
+
nx run gw-tool:npm-pack
|
|
570
|
+
|
|
571
|
+
# Link the package globally
|
|
572
|
+
cd dist/packages/gw-tool/npm
|
|
573
|
+
npm link
|
|
574
|
+
|
|
575
|
+
# Now `gw` is available globally via npm
|
|
576
|
+
gw sync feat-branch .env
|
|
577
|
+
|
|
578
|
+
# When you make changes
|
|
579
|
+
cd ~/path/to/gw-tools
|
|
580
|
+
nx run gw-tool:compile-all
|
|
581
|
+
nx run gw-tool:npm-pack
|
|
582
|
+
# The link automatically uses the updated binaries
|
|
583
|
+
|
|
584
|
+
# To unlink when done
|
|
585
|
+
npm unlink -g @gw-tools/gw
|
|
586
|
+
```
|
|
587
|
+
|
|
588
|
+
#### Watch Mode for Active Development
|
|
589
|
+
|
|
590
|
+
Use the watch mode to automatically restart when files change:
|
|
591
|
+
|
|
592
|
+
```bash
|
|
593
|
+
# Terminal 1: Run in watch mode
|
|
594
|
+
nx run gw-tool:dev
|
|
595
|
+
|
|
596
|
+
# Terminal 2: Test in another project
|
|
597
|
+
cd ~/some-project
|
|
598
|
+
~/path/to/gw-tools/dist/packages/gw-tool/gw sync feat-branch .env
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
**Pro tip**: Combine Method 3 (wrapper script) with watch mode by setting `GW_DEV=1` in your development shell.
|
|
602
|
+
|
|
125
603
|
### Available Scripts
|
|
126
604
|
|
|
127
605
|
```bash
|
|
@@ -287,13 +765,32 @@ packages/gw-tool/
|
|
|
287
765
|
│ ├── main.ts # CLI entry point and command dispatcher
|
|
288
766
|
│ ├── index.ts # Public API exports
|
|
289
767
|
│ ├── commands/ # Command implementations
|
|
290
|
-
│ │
|
|
768
|
+
│ │ ├── add.ts # Add command (create worktree with auto-copy)
|
|
769
|
+
│ │ ├── copy.ts # Sync command (sync files between worktrees)
|
|
770
|
+
│ │ ├── init.ts # Init command
|
|
771
|
+
│ │ ├── root.ts # Root command
|
|
772
|
+
│ │ ├── list.ts # List command (proxy)
|
|
773
|
+
│ │ ├── remove.ts # Remove command (proxy)
|
|
774
|
+
│ │ ├── move.ts # Move command (proxy)
|
|
775
|
+
│ │ ├── prune.ts # Prune command (proxy)
|
|
776
|
+
│ │ ├── lock.ts # Lock command (proxy)
|
|
777
|
+
│ │ ├── unlock.ts # Unlock command (proxy)
|
|
778
|
+
│ │ └── repair.ts # Repair command (proxy)
|
|
291
779
|
│ └── lib/ # Shared utilities
|
|
292
780
|
│ ├── types.ts # TypeScript type definitions
|
|
293
781
|
│ ├── config.ts # Configuration management
|
|
294
|
-
│ ├── cli.ts # CLI argument parsing
|
|
782
|
+
│ ├── cli.ts # CLI argument parsing & help
|
|
295
783
|
│ ├── file-ops.ts # File/directory operations
|
|
296
|
-
│
|
|
784
|
+
│ ├── path-resolver.ts # Path resolution utilities
|
|
785
|
+
│ ├── output.ts # Colored output formatting
|
|
786
|
+
│ └── git-proxy.ts # Git command proxy utilities
|
|
787
|
+
├── npm/ # npm package files
|
|
788
|
+
│ ├── package.json # npm package metadata
|
|
789
|
+
│ ├── install.js # Binary installation script
|
|
790
|
+
│ └── bin/
|
|
791
|
+
│ └── gw.js # Binary wrapper
|
|
792
|
+
├── scripts/
|
|
793
|
+
│ └── release.sh # Automated release script
|
|
297
794
|
├── deno.json # Deno configuration
|
|
298
795
|
├── project.json # Nx project configuration
|
|
299
796
|
└── README.md # This file
|
|
@@ -301,43 +798,94 @@ packages/gw-tool/
|
|
|
301
798
|
|
|
302
799
|
### Adding New Commands
|
|
303
800
|
|
|
304
|
-
|
|
801
|
+
There are two types of commands you can add:
|
|
305
802
|
|
|
306
|
-
|
|
307
|
-
|
|
803
|
+
#### Custom Commands (like `add`, `copy`)
|
|
804
|
+
|
|
805
|
+
For commands with custom logic, follow the pattern used by existing commands:
|
|
806
|
+
|
|
807
|
+
1. **Create a new file** in `src/commands/` (e.g., `list.ts`):
|
|
308
808
|
```typescript
|
|
309
|
-
|
|
809
|
+
// src/commands/list.ts
|
|
810
|
+
export async function executeList(args: string[]): Promise<void> {
|
|
811
|
+
// Check for help flag
|
|
812
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
813
|
+
console.log(`Usage: gw list
|
|
814
|
+
|
|
815
|
+
List all git worktrees in the current repository.
|
|
816
|
+
|
|
817
|
+
Options:
|
|
818
|
+
-h, --help Show this help message
|
|
819
|
+
`);
|
|
820
|
+
Deno.exit(0);
|
|
821
|
+
}
|
|
822
|
+
|
|
310
823
|
// Command implementation
|
|
824
|
+
// ...
|
|
311
825
|
}
|
|
312
826
|
```
|
|
313
|
-
|
|
827
|
+
|
|
828
|
+
2. **Import and register** the command in `src/main.ts`:
|
|
314
829
|
```typescript
|
|
830
|
+
import { executeList } from "./commands/list.ts";
|
|
831
|
+
|
|
315
832
|
const COMMANDS = {
|
|
316
|
-
|
|
317
|
-
|
|
833
|
+
add: executeAdd,
|
|
834
|
+
sync: executeCopy,
|
|
835
|
+
init: executeInit,
|
|
836
|
+
root: executeRoot,
|
|
837
|
+
list: executeList, // Add your new command
|
|
318
838
|
};
|
|
319
839
|
```
|
|
320
840
|
|
|
321
|
-
|
|
841
|
+
3. **Update global help** in `src/lib/cli.ts`:
|
|
842
|
+
```typescript
|
|
843
|
+
export function showGlobalHelp(): void {
|
|
844
|
+
console.log(`
|
|
845
|
+
Commands:
|
|
846
|
+
add Create a new worktree with optional auto-copy
|
|
847
|
+
sync Sync files/directories between worktrees
|
|
848
|
+
init Initialize gw configuration for a repository
|
|
849
|
+
root Get the root directory of the current git repository
|
|
850
|
+
list List all git worktrees in the repository
|
|
851
|
+
`);
|
|
852
|
+
}
|
|
853
|
+
```
|
|
322
854
|
|
|
323
|
-
|
|
855
|
+
#### Git Proxy Commands (like `list`, `remove`)
|
|
324
856
|
|
|
325
|
-
|
|
857
|
+
For simple pass-through commands that wrap git worktree operations, use the `git-proxy` utility:
|
|
326
858
|
|
|
327
|
-
|
|
859
|
+
1. **Create a new file** in `src/commands/` (e.g., `list.ts`):
|
|
860
|
+
```typescript
|
|
861
|
+
// src/commands/list.ts
|
|
862
|
+
import { executeGitWorktree, showProxyHelp } from '../lib/git-proxy.ts';
|
|
863
|
+
|
|
864
|
+
export async function executeList(args: string[]): Promise<void> {
|
|
865
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
866
|
+
showProxyHelp(
|
|
867
|
+
'list',
|
|
868
|
+
'list',
|
|
869
|
+
'List all worktrees in the repository',
|
|
870
|
+
['gw list', 'gw list --porcelain', 'gw list -v'],
|
|
871
|
+
);
|
|
872
|
+
Deno.exit(0);
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
await executeGitWorktree('list', args);
|
|
876
|
+
}
|
|
877
|
+
```
|
|
328
878
|
|
|
329
|
-
|
|
330
|
-
# From within any worktree of your repository
|
|
331
|
-
# Create a new worktree
|
|
332
|
-
git worktree add feat-new-feature
|
|
879
|
+
2. **Register** in `src/main.ts` (same as above)
|
|
333
880
|
|
|
334
|
-
|
|
335
|
-
# gw automatically detects your repository and uses its config
|
|
336
|
-
gw copy feat-new-feature .env components/agents/.env components/ui/.vercel
|
|
881
|
+
3. **Update global help** in `src/lib/cli.ts` (same as above)
|
|
337
882
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
883
|
+
This approach requires minimal maintenance as it simply forwards all arguments to git.
|
|
884
|
+
|
|
885
|
+
**Tips**:
|
|
886
|
+
- Look at [src/commands/root.ts](src/commands/root.ts) for a simple custom command
|
|
887
|
+
- Look at [src/commands/copy.ts](src/commands/copy.ts) for a complex command with argument parsing
|
|
888
|
+
- Look at [src/commands/list.ts](src/commands/list.ts) for a simple proxy command
|
|
341
889
|
|
|
342
890
|
## License
|
|
343
891
|
|