git-p4son 0.4.2__tar.gz → 0.5.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.
Files changed (74) hide show
  1. {git_p4son-0.4.2 → git_p4son-0.5.1}/PKG-INFO +189 -74
  2. {git_p4son-0.4.2 → git_p4son-0.5.1}/README.md +188 -73
  3. git_p4son-0.5.1/git_p4son/__init__.py +7 -0
  4. {git_p4son-0.4.2 → git_p4son-0.5.1}/git_p4son/__main__.py +1 -3
  5. {git_p4son-0.4.2 → git_p4son-0.5.1}/git_p4son/alias.py +22 -8
  6. {git_p4son-0.4.2 → git_p4son-0.5.1}/git_p4son/changelist_store.py +5 -17
  7. {git_p4son-0.4.2 → git_p4son-0.5.1}/git_p4son/cli.py +206 -71
  8. {git_p4son-0.4.2 → git_p4son-0.5.1}/git_p4son/common.py +15 -69
  9. {git_p4son-0.4.2 → git_p4son-0.5.1}/git_p4son/complete.py +24 -25
  10. {git_p4son-0.4.2 → git_p4son-0.5.1}/git_p4son/config.py +3 -16
  11. {git_p4son-0.4.2 → git_p4son-0.5.1}/git_p4son/depot.py +4 -19
  12. {git_p4son-0.4.2 → git_p4son-0.5.1}/git_p4son/git.py +18 -72
  13. {git_p4son-0.4.2 → git_p4son-0.5.1}/git_p4son/hooks.py +1 -2
  14. {git_p4son-0.4.2 → git_p4son-0.5.1}/git_p4son/init.py +67 -32
  15. {git_p4son-0.4.2 → git_p4son-0.5.1}/git_p4son/lib.py +62 -55
  16. {git_p4son-0.4.2 → git_p4son-0.5.1}/git_p4son/list_changes.py +1 -3
  17. {git_p4son-0.4.2 → git_p4son-0.5.1}/git_p4son/log.py +8 -31
  18. {git_p4son-0.4.2 → git_p4son-0.5.1}/git_p4son/new.py +5 -20
  19. {git_p4son-0.4.2 → git_p4son-0.5.1}/git_p4son/perforce.py +29 -84
  20. {git_p4son-0.4.2 → git_p4son-0.5.1}/git_p4son/processes.py +5 -23
  21. git_p4son-0.5.1/git_p4son/rebase_todo.py +101 -0
  22. git_p4son-0.5.1/git_p4son/review.py +98 -0
  23. git_p4son-0.5.1/git_p4son/skill/SKILL.md +8 -0
  24. git_p4son-0.5.1/git_p4son/skill/git-p4son.md +232 -0
  25. git_p4son-0.5.1/git_p4son/skill.py +64 -0
  26. {git_p4son-0.4.2 → git_p4son-0.5.1}/git_p4son/state.py +1 -6
  27. {git_p4son-0.4.2 → git_p4son-0.5.1}/git_p4son/sync.py +156 -221
  28. git_p4son-0.5.1/git_p4son/sync_split_users.py +177 -0
  29. git_p4son-0.5.1/git_p4son/update.py +127 -0
  30. {git_p4son-0.4.2 → git_p4son-0.5.1}/git_p4son/writable.py +6 -25
  31. {git_p4son-0.4.2 → git_p4son-0.5.1}/git_p4son.egg-info/PKG-INFO +189 -74
  32. {git_p4son-0.4.2 → git_p4son-0.5.1}/git_p4son.egg-info/SOURCES.txt +8 -2
  33. {git_p4son-0.4.2 → git_p4son-0.5.1}/pyproject.toml +2 -2
  34. {git_p4son-0.4.2 → git_p4son-0.5.1}/tests/test_alias.py +55 -1
  35. {git_p4son-0.4.2 → git_p4son-0.5.1}/tests/test_cli.py +152 -6
  36. {git_p4son-0.4.2 → git_p4son-0.5.1}/tests/test_complete.py +57 -3
  37. {git_p4son-0.4.2 → git_p4son-0.5.1}/tests/test_git.py +0 -8
  38. {git_p4son-0.4.2 → git_p4son-0.5.1}/tests/test_init.py +130 -15
  39. {git_p4son-0.4.2 → git_p4son-0.5.1}/tests/test_lib_changelist.py +144 -0
  40. {git_p4son-0.4.2 → git_p4son-0.5.1}/tests/test_new.py +2 -1
  41. {git_p4son-0.4.2 → git_p4son-0.5.1}/tests/test_perforce.py +34 -1
  42. git_p4son-0.5.1/tests/test_rebase_todo.py +147 -0
  43. {git_p4son-0.4.2 → git_p4son-0.5.1}/tests/test_review.py +95 -113
  44. git_p4son-0.5.1/tests/test_skill.py +85 -0
  45. {git_p4son-0.4.2 → git_p4son-0.5.1}/tests/test_sync.py +362 -45
  46. git_p4son-0.5.1/tests/test_sync_split_users.py +273 -0
  47. git_p4son-0.5.1/tests/test_update.py +209 -0
  48. git_p4son-0.4.2/git_p4son/__init__.py +0 -12
  49. git_p4son-0.4.2/git_p4son/review.py +0 -184
  50. git_p4son-0.4.2/git_p4son/sync_split.py +0 -166
  51. git_p4son-0.4.2/git_p4son/update.py +0 -68
  52. git_p4son-0.4.2/tests/test_sync_split.py +0 -497
  53. git_p4son-0.4.2/tests/test_update.py +0 -85
  54. {git_p4son-0.4.2 → git_p4son-0.5.1}/LICENSE +0 -0
  55. {git_p4son-0.4.2 → git_p4son-0.5.1}/git_p4son/completions/_git-p4son +0 -0
  56. {git_p4son-0.4.2 → git_p4son-0.5.1}/git_p4son/completions/git-p4son.bash +0 -0
  57. {git_p4son-0.4.2 → git_p4son-0.5.1}/git_p4son/completions/git-p4son.ps1 +0 -0
  58. {git_p4son-0.4.2 → git_p4son-0.5.1}/git_p4son.egg-info/dependency_links.txt +0 -0
  59. {git_p4son-0.4.2 → git_p4son-0.5.1}/git_p4son.egg-info/entry_points.txt +0 -0
  60. {git_p4son-0.4.2 → git_p4son-0.5.1}/git_p4son.egg-info/top_level.txt +0 -0
  61. {git_p4son-0.4.2 → git_p4son-0.5.1}/setup.cfg +0 -0
  62. {git_p4son-0.4.2 → git_p4son-0.5.1}/tests/test_changelist_store.py +0 -0
  63. {git_p4son-0.4.2 → git_p4son-0.5.1}/tests/test_common.py +0 -0
  64. {git_p4son-0.4.2 → git_p4son-0.5.1}/tests/test_config.py +0 -0
  65. {git_p4son-0.4.2 → git_p4son-0.5.1}/tests/test_depot.py +0 -0
  66. {git_p4son-0.4.2 → git_p4son-0.5.1}/tests/test_hooks.py +0 -0
  67. {git_p4son-0.4.2 → git_p4son-0.5.1}/tests/test_lib_edit.py +0 -0
  68. {git_p4son-0.4.2 → git_p4son-0.5.1}/tests/test_lib_revert.py +0 -0
  69. {git_p4son-0.4.2 → git_p4son-0.5.1}/tests/test_lib_review.py +0 -0
  70. {git_p4son-0.4.2 → git_p4son-0.5.1}/tests/test_list_changes.py +0 -0
  71. {git_p4son-0.4.2 → git_p4son-0.5.1}/tests/test_log.py +0 -0
  72. {git_p4son-0.4.2 → git_p4son-0.5.1}/tests/test_processes.py +0 -0
  73. {git_p4son-0.4.2 → git_p4son-0.5.1}/tests/test_state.py +0 -0
  74. {git_p4son-0.4.2 → git_p4son-0.5.1}/tests/test_writable.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: git-p4son
3
- Version: 0.4.2
3
+ Version: 0.5.1
4
4
  Summary: Utility for keeping a Perforce workspace and local git repo in sync
5
5
  Author-email: Andreas Andersson <andreas@neoboid.com>
6
6
  License-Expression: MIT
@@ -118,7 +118,8 @@ Requires Python 3.11 or later.
118
118
  pip install --upgrade git-p4son
119
119
  ```
120
120
 
121
- For tab completion (zsh and PowerShell), see [Shell Completions](#shell-completions).
121
+ For tab completion (zsh and PowerShell), see [Shell Completions](#shell-completions). To let Claude Code drive
122
+ git-p4son, see [Claude Code Skill](#claude-code-skill).
122
123
 
123
124
  ## Development
124
125
 
@@ -198,8 +199,8 @@ workflow.
198
199
  ### How sync handles writable files
199
200
 
200
201
  When you switch branches with `git checkout`, git removes the read-only flag on every file it writes. This means
201
- that when you switch back to `main` for a sync, Perforce may report "Can't clobber writable file" errors. git-p4son
202
- handles these automatically by classifying each writable file:
202
+ that when you switch back to `main` for a sync, Perforce may refuse to overwrite those files because they are
203
+ writable. git-p4son handles these automatically by classifying each writable file:
203
204
 
204
205
  **writable-unchanged** - The file on disk is identical to the last sync (only the read-only flag was removed
205
206
  by git). This is the common case after switching branches. git-p4son detects this by comparing git blob IDs against
@@ -233,19 +234,19 @@ commit any files that need attention.
233
234
 
234
235
  **Workspaces with `allwrite`** - When your client spec has the `allwrite` option, every file is writable by design,
235
236
  so the read-only flag carries no information about local changes. git-p4son classifies files exactly as above (the
236
- verdict comes from git, not from the flag), but leaves the write bit alone on files it finds unchanged: with
237
- `noclobber` Perforce compares digests before refusing to overwrite a writable file, and unchanged files pass that
238
- check. Only files with local changes are made read-only for the duration of the sync, since those are the ones
239
- Perforce would otherwise refuse to overwrite. The same digest check applies to git-ignored files: unchanged ones sync
240
- normally, and after the sync git-p4son lists the ones Perforce skipped because they were modified locally.
237
+ verdict comes from git, not from the flag), but leaves the write bit alone on files it finds unchanged: Perforce
238
+ compares digests before refusing to overwrite a writable file, and unchanged files pass that check. Only files with
239
+ local changes are made read-only for the duration of the sync, since those are the ones Perforce would otherwise
240
+ refuse to overwrite. The same digest check applies to git-ignored files: unchanged ones sync normally, and after the
241
+ sync git-p4son lists the ones Perforce skipped because they were modified locally.
241
242
 
242
243
  **Writable mode** - With [writable mode](#writable-command) on, the files a sync touches are made writable again after
243
244
  the sync if git tracks them. The sync itself works as described above, since the workspace is not `allwrite`.
244
245
 
245
246
  ## Usage
246
247
 
247
- git-p4son provides ten commands: `init`, `sync`, `sync-split`, `new`, `update`, `review`, `list-changes`,
248
- `alias`, `writable`, and `completion`.
248
+ git-p4son provides eleven commands: `init`, `sync`, `sync-split-users`, `new`, `update`, `review`,
249
+ `list-changes`, `alias`, `writable`, `completion`, and `skill`.
249
250
 
250
251
  To see help for any command, use `-h`:
251
252
 
@@ -293,12 +294,19 @@ The `.gitignore` is set up using this priority:
293
294
  `init` also asks whether to turn on [writable mode](#writable-command), defaulting to the current setting. It only
294
295
  saves the answer; run `git p4son writable apply` once your files are committed to update their permissions.
295
296
 
297
+ `init` then asks whether to sync your own changelists individually, making you a [split user](#split-users).
298
+ The default is the current setting. Yes adds a `$(user)` entry to the split users and no removes it; other split
299
+ users are left alone.
300
+
301
+ Finally, if Claude Code is installed, `init` offers to install the [Claude Code skill](#claude-code-skill). An
302
+ already installed skill is refreshed without asking.
303
+
296
304
  ### Sync Command
297
305
 
298
306
  Sync local git repository with a Perforce workspace:
299
307
 
300
308
  ```sh
301
- git p4son sync [changelist ...] [--force] [--dry-run] [--ignore-blocking-processes]
309
+ git p4son sync [changelist ...] [--force] [--dry-run] [--split-user NAME ...] [--no-split] [--ignore-blocking-processes]
302
310
  ```
303
311
 
304
312
  **Arguments:**
@@ -311,6 +319,10 @@ git p4son sync [changelist ...] [--force] [--dry-run] [--ignore-blocking-process
311
319
  - `-f, --force`: Allow syncing to changelists older than the current one.
312
320
  - `-n, --dry-run`: Print the resolved sync sequence without syncing. The arguments are validated as for a
313
321
  real sync, but nothing else runs: no clean-workspace checks, no hooks, and no prompts.
322
+ - `-u, --split-user NAME`: Also split out this user's changelists, on top of the configured
323
+ [split users](#split-users). Repeat to give several users. Each name is checked against the Perforce server.
324
+ - `--no-split`: Ignore the configured split users for this sync. Users given with `--split-user` are still split
325
+ out, so `--no-split -u alice` splits out only alice's changelists.
314
326
  - `--ignore-blocking-processes`: Sync even while a [blocking process](#blocking-processes) is running.
315
327
 
316
328
  **Examples:**
@@ -323,6 +335,8 @@ git p4son sync 123 156 head # sync 123, 156, then the latest changelist
323
335
  git p4son sync last-synced
324
336
  git p4son sync 12345 --force
325
337
  git p4son sync --dry-run # show the changelists a sync to latest would visit
338
+ git p4son sync -u alice # also split out alice's changelists
339
+ git p4son sync --no-split # sync without splitting out the configured split users
326
340
  ```
327
341
 
328
342
  #### Blocking processes
@@ -343,6 +357,37 @@ skipping the check.
343
357
 
344
358
  Pass `--ignore-blocking-processes` to sync once without the check, or remove the setting to turn it off for good.
345
359
 
360
+ #### Split users
361
+
362
+ Syncing straight to the latest changelist lumps your own submitted changelists together with everyone else's in a
363
+ single commit. Split users fix that: for each changelist a split user submitted since the last sync, `sync` first
364
+ syncs the changelist submitted immediately before it, so every changelist they submitted becomes a commit containing
365
+ nothing but their own change.
366
+
367
+ The split users are stored in `.git-p4son/config.toml`, and edited with the
368
+ [`sync-split-users` command](#sync-split-users-command) or by answering yes in `init`:
369
+
370
+ ```toml
371
+ [sync]
372
+ split-users = ["$(user)", "alice"]
373
+ ```
374
+
375
+ `$(user)` stands for the current Perforce user (from `p4 info`), resolved each time `sync` runs, so the config
376
+ survives a change of user, the same way `$(workspace)` works in the depot root.
377
+
378
+ For example, with the last sync at CL 100, your own changelists at 102 and 105, and the latest changelist at 106,
379
+ `sync` visits `101 102 104 105 106`, producing five commits where CL 102 and CL 105 each hold only your change.
380
+ Changelists given on the command line are all still visited, with the split points merged in: `sync 103 head`
381
+ visits `101 102 103 104 105 106`.
382
+
383
+ Splitting only moves forward from a previous sync. The first sync, `last-synced`, and syncing to an older changelist
384
+ with `--force` are never split. Without any split users, `sync` makes no extra Perforce queries.
385
+
386
+ Finding the split users' changelists costs one extra Perforce query over the range being synced. It runs after the
387
+ blocking processes check, the clean-workspace checks and the pre-sync hooks, so a running blocking process, a dirty
388
+ workspace or a hook that aborts the sync says so before that work. `--dry-run` skips the checks and hooks but still
389
+ shows the resulting sequence.
390
+
346
391
  #### pre-sync hook
347
392
 
348
393
  Before `git-p4son sync` syncs any changelist, git-p4son runs [hooks](#hooks) from
@@ -354,78 +399,51 @@ changelists is given, the pre-sync hooks run once, before the first sync.
354
399
  After a successful `git-p4son sync` that actually performs sync work, git-p4son runs [hooks](#hooks)
355
400
  from `.git-p4son/hooks/post-sync/`.
356
401
 
357
- ### Sync-Split Command
358
-
359
- Sync forward from the last synced changelist, splitting selected users' changelists into their own commits:
402
+ ### Sync-Split-Users Command
360
403
 
361
- ```sh
362
- git p4son sync-split [changelist] [--user NAME ...] [--dry-run] [--ignore-blocking-processes]
363
- ```
364
-
365
- Syncing straight to the latest changelist lumps your own submitted changelists together with everyone
366
- else's in a single commit. `sync-split` resolves the sequence for you: it looks up the last synced
367
- changelist in the git log, asks Perforce which changelists the selected users submitted since then, and
368
- syncs the changelist submitted immediately before each of those first. The result is a git history where
369
- every changelist those users submitted is a commit containing nothing but their own change.
370
-
371
- By default the selected user is you (the current p4 user), which covers the common case of reviewing your
372
- own submits one at a time. Repeat `--user` to split out several people's changelists in the same run.
373
-
374
- It is equivalent to working out the numbers by hand and running
375
- `git p4son sync <before-theirs> <theirs> ... head`, and it delegates to `sync` once the sequence is
376
- resolved, so [pre-sync and post-sync hooks](#hooks), [blocking processes](#blocking-processes), writable-file
377
- merging, and the clean-workspace checks all behave exactly as they do for `sync`. The blocking processes check,
378
- the clean-workspace checks and the pre-sync hooks are the one thing that runs earlier: resolving the sequence
379
- costs several Perforce queries, so they go first, and a running blocking process, a dirty workspace or a hook
380
- that aborts the sync says so before that work. They run once for the whole sync, and not at all for a
381
- `--dry-run` or when there is nothing to sync.
382
-
383
- **Arguments:**
384
- - `changelist` (optional): Changelist number to sync up to, or `head` for the latest. Omit to sync to the
385
- latest changelist affecting the workspace.
404
+ Show or edit the [split users](#split-users), the Perforce users whose changelists `sync` gives a commit each:
386
405
 
387
- **Options:**
388
- - `-u, --user NAME`: Perforce user whose changelists to split into their own commits. Repeat the flag to
389
- select several users. Defaults to the current p4 user (from `p4 info`).
390
- - `-n, --dry-run`: Print the resolved sync sequence without syncing.
391
- - `--ignore-blocking-processes`: Sync even while a [blocking process](#blocking-processes) is running.
392
-
393
- **Examples:**
394
406
  ```sh
395
- git p4son sync-split # sync to latest, your own changelists split out
396
- git p4son sync-split head # same, explicit
397
- git p4son sync-split 12345 # stop at changelist 12345
398
- git p4son sync-split --dry-run # show the sequence that would be synced
399
- git p4son sync-split -u alice # split out alice's changelists instead of yours
400
- git p4son sync-split -u alice -u bob # split out both alice's and bob's changelists
407
+ git p4son sync-split-users # list the split users (same as list)
408
+ git p4son sync-split-users list
409
+ git p4son sync-split-users add --me # add yourself, stored as $(user)
410
+ git p4son sync-split-users add alice bob
411
+ git p4son sync-split-users delete alice
412
+ git p4son sync-split-users delete --me
401
413
  ```
402
414
 
403
- For example, with the last sync at CL 100 and your own changelists at 102 and 105, `sync-split` resolves
404
- to `git p4son sync 101 102 104 105 106`, producing five commits where CL 102 and CL 105 each hold only
405
- your change.
415
+ - `list` prints one user per line. `$(user)` is shown with the name it stands for, e.g. `$(user) (alice)`.
416
+ - `add` checks every name against the Perforce server first, since a misspelled name would never match a
417
+ changelist. If any name is not a Perforce user, nothing is added. Names are stored as the server spells them,
418
+ and a name that is already a split user is skipped.
419
+ - `delete` removes names regardless of case. If any name is not a split user, nothing is removed.
406
420
 
407
- `sync-split` only moves forward: it requires a previous sync to start from, and refuses a target older
408
- than the last synced changelist (use `git p4son sync --force` for that).
421
+ `--me` adds or removes the `$(user)` entry. A quoted `'$(user)'` does the same, but the quotes matter: unquoted,
422
+ bash, zsh and PowerShell run `$(user)` as a command substitution.
409
423
 
410
424
  ### New Command
411
425
 
412
- Create a new Perforce changelist and add changed files to it. Description will contain an enumerated list of git commits since the base branch.
413
- Optionally creates a Swarm review.
426
+ Create a new Perforce changelist and add changed files to it. Description will contain an enumerated list of git commits
427
+ since the base branch. Optionally creates a Swarm review.
414
428
 
415
429
  Opening files requires a clean git workspace, untracked files included; `new` refuses to run otherwise. The check
416
430
  is skipped with `--no-edit`. After opening files, unchanged ones are reverted (see
417
431
  [Keeping the changelist in step with git](#keeping-the-changelist-in-step-with-git)).
418
432
 
419
433
  ```sh
420
- git p4son new -m <message> [alias] [--base-branch BASE_BRANCH] [--force] [--dry-run] [--no-edit] [--no-alias]
421
- [--shelve] [--review]
434
+ git p4son new [-m <message> | -F <file>] [alias] [--base-branch BASE_BRANCH] [--force] [--dry-run] [--no-edit]
435
+ [--no-alias] [--no-commit-list] [--shelve] [--review]
422
436
  ```
423
437
 
424
438
  **Arguments:**
425
439
  - `alias` (optional): Alias name to save the new changelist number under. Defaults to the current branch name.
426
440
 
427
441
  **Options:**
428
- - `-m, --message MESSAGE`: Changelist description message (required)
442
+ - `-m, --message MESSAGE`: Changelist description message. Defaults to the HEAD commit subject
443
+ - `-F, --file FILE`: Read the changelist description message from a file instead of `-m`. The message may span
444
+ multiple lines
445
+ - `--no-commit-list`: Leave the enumerated commit list out of the changelist description, so it holds only the
446
+ message
429
447
  - `-b, --base-branch BASE_BRANCH`: Base branch for enumerating commits and finding changed files. Default is
430
448
  `HEAD~1`
431
449
  - `-f, --force`: Overwrite an existing alias file
@@ -450,26 +468,44 @@ git p4son new -m "New feature" --review -b main
450
468
  Update an existing Perforce changelist description. Commits since the base branch replace their existing
451
469
  entries in the enumerated commit list (matched by subject) and new ones are appended; entries outside the
452
470
  range are kept and the list is renumbered. So `update -b main` rebuilds the whole list without duplicating
453
- it, while `update -b HEAD~3` only refreshes the last three entries. By default also opens changed files for
471
+ it, while `update -b HEAD~3` only refreshes the last three entries. The message above the list is kept unless `-m`
472
+ or `-F` replaces it. By default also opens changed files for
454
473
  edit, and reverts files that are no longer part of the git change (see
455
474
  [Keeping the changelist in step with git](#keeping-the-changelist-in-step-with-git)). Opening files requires a
456
475
  clean git workspace, untracked files included; `update` refuses to run otherwise. The check is skipped with
457
476
  `--no-edit`.
458
477
 
478
+ With `--per-commit`, `update` runs once per commit since the base branch instead of once for the whole range, the
479
+ way `review` does after creating the changelist. It replays the commits with an interactive rebase, without opening
480
+ an editor, and runs `git p4son update` after each one. With `--shelve`, every commit gets a shelf of its own and so
481
+ shows up as its own patch in the Swarm review. Use it after making several commits since the last update:
482
+ `update -b HEAD~2 --per-commit --shelve` updates the changelist with the last two commits, one at a time. The
483
+ changelist is resolved before the rebase starts, and `-m`/`-F` is applied on the first step only. The rebase needs a
484
+ clean git workspace, also with `--no-edit`. If a step fails, the rebase stops; fix the problem and run
485
+ `git rebase --continue`.
486
+
459
487
  ```sh
460
- git p4son update [changelist] [--base-branch BASE_BRANCH] [--dry-run] [--no-desc] [--no-edit] [--shelve]
488
+ git p4son update [changelist] [-m <message> | -F <file>] [--base-branch BASE_BRANCH] [--dry-run]
489
+ [--no-commit-list] [--no-edit] [--shelve] [--per-commit]
461
490
  ```
462
491
 
463
492
  **Arguments:**
464
493
  - `changelist` (optional): Changelist number or named alias to update. Defaults to the current branch name.
465
494
 
466
495
  **Options:**
496
+ - `-m, --message MESSAGE`: Replace the changelist description message above the commit list. The commit list is
497
+ kept and updated as usual, and so is a Swarm `#review` keyword on a line of its own at the end of the description
498
+ - `-F, --file FILE`: Like `-m`, but read the message from a file. The message may span multiple lines
467
499
  - `-b, --base-branch BASE_BRANCH`: Base branch for enumerating commits and finding changed files. Default is
468
500
  `HEAD~1`
469
501
  - `-n, --dry-run`: Pretend and print what would be done, but do not execute
470
- - `--no-desc`: Skip updating the changelist description
502
+ - `--no-commit-list`: Leave the enumerated commit list as it is. Without `-m` or `-F` the description is not
503
+ touched at all
471
504
  - `--no-edit`: Skip opening changed files for edit in Perforce
472
505
  - `--shelve`: Re-shelve the changelist after updating
506
+ - `--per-commit`: Update the changelist once per commit since the base branch, oldest first, through an
507
+ interactive rebase. Steps sleep 5 seconds between them to give Perforce/Swarm time to process each shelf.
508
+ `--dry-run` prints the generated rebase todo
473
509
  - `-s, --sleep SECONDS`: Sleep for the specified number of seconds after the command is done
474
510
 
475
511
  **Examples:**
@@ -478,6 +514,8 @@ git p4son update # update changelist for current branch
478
514
  git p4son update --shelve # update and re-shelve
479
515
  git p4son update 12345
480
516
  git p4son update myalias -b main
517
+ git p4son update -F description.txt # replace the message, e.g. after review feedback
518
+ git p4son update -b HEAD~2 --per-commit --shelve # one shelf for each of the last two commits
481
519
  ```
482
520
 
483
521
  ### Keeping the changelist in step with git
@@ -503,20 +541,30 @@ are left out of it.
503
541
 
504
542
  ### Review Command
505
543
 
506
- Automate the interactive rebase workflow for creating Swarm reviews. This command generates a rebase todo with `exec` lines that run `git p4son new --review` on the first commit and `git p4son update --shelve` on each subsequent commit, then opens it in your editor for review before executing.
544
+ Automate the interactive rebase workflow for creating Swarm reviews. This command generates a rebase todo with `exec`
545
+ lines that run `git p4son new --review` on the first commit and `git p4son update --shelve` on each subsequent commit,
546
+ then opens it in your editor for review before executing.
507
547
 
508
548
  ```sh
509
- git p4son review [alias] -m <message> [--base-branch BASE_BRANCH] [--force] [--dry-run]
549
+ git p4son review [alias] [-m <message> | -F <file>] [--base-branch BASE_BRANCH] [--force] [--dry-run]
550
+ [--no-commit-list] [--no-edit-todo]
510
551
  ```
511
552
 
512
553
  **Arguments:**
513
554
  - `alias` (optional): Alias name for the new changelist. Defaults to the current branch name.
514
555
 
515
556
  **Options:**
516
- - `-m, --message MESSAGE`: Changelist description message (required)
557
+ - `-m, --message MESSAGE`: Changelist description message. Defaults to the HEAD commit subject
558
+ - `-F, --file FILE`: Read the changelist description message from a file instead of `-m`. The message may span
559
+ multiple lines. The generated `exec` line passes the file on to `git p4son new -F`, so keep it in place until the
560
+ rebase has finished
517
561
  - `-b, --base-branch BASE_BRANCH`: Base branch to rebase onto and find commits since. Default is `HEAD~1`
518
562
  - `-f, --force`: Overwrite an existing alias file
519
563
  - `-n, --dry-run`: Print the generated rebase todo without executing
564
+ - `--no-commit-list`: Leave the enumerated commit list out of the changelist description. Passed on to `new` and
565
+ each `update` in the rebase todo
566
+ - `--no-edit-todo`: Accept the generated rebase todo as is and start the rebase without opening an editor. No
567
+ editor needs to be configured. Useful for scripts and AI agents, which can check the todo with `--dry-run` first
520
568
 
521
569
  When run, the command generates a todo like this and opens it in your editor:
522
570
 
@@ -529,7 +577,8 @@ pick ghi9012 Third commit
529
577
  exec git p4son update my-feature --shelve
530
578
  ```
531
579
 
532
- You can edit the todo before saving (e.g. reorder commits, remove lines), or abort by clearing the file — just like a normal `git rebase -i`. Each `exec` line automatically sleeps after shelving to give Perforce/Swarm time to process.
580
+ You can edit the todo before saving (e.g. reorder commits, remove lines), or abort by clearing the file - just like a
581
+ normal `git rebase -i`. Each `exec` line automatically sleeps after shelving to give Perforce/Swarm time to process.
533
582
 
534
583
  If the rebase fails mid-way, you can fix the issue and run `git rebase --continue` as usual.
535
584
 
@@ -543,6 +592,12 @@ git p4son review -m "Fix bug"
543
592
 
544
593
  # Preview the generated todo without executing
545
594
  git p4son review -m "Add my feature" -b main --dry-run
595
+
596
+ # Take a multi-line description from a file
597
+ git p4son review -F description.txt -b main
598
+
599
+ # Run the rebase without reviewing the todo in an editor
600
+ git p4son review -m "Add my feature" -b main --no-edit-todo
546
601
  ```
547
602
 
548
603
  ### List-Changes Command
@@ -562,7 +617,8 @@ git p4son list-changes
562
617
  git p4son list-changes --base-branch main
563
618
  ```
564
619
 
565
- This command is useful for generating changelist descriptions by listing all commit messages since the base branch, numbered sequentially.
620
+ This command is useful for generating changelist descriptions by listing all commit messages since the base branch,
621
+ numbered sequentially.
566
622
 
567
623
  ### Alias Command
568
624
 
@@ -581,6 +637,27 @@ git p4son alias list
581
637
  git p4son alias list
582
638
  ```
583
639
 
640
+ #### alias show
641
+
642
+ Print the changelist number saved under an alias:
643
+
644
+ ```sh
645
+ git p4son alias show [alias]
646
+ ```
647
+
648
+ Only the number is printed to stdout, so scripts and AI agents can capture it, e.g. to find the changelist that
649
+ `new` or `review` created. Exits with an error if the alias does not exist.
650
+
651
+ **Arguments:**
652
+ - `alias` (optional): Alias name to show. Defaults to the current branch name.
653
+
654
+ **Examples:**
655
+ ```sh
656
+ git p4son alias show # changelist for current branch
657
+ git p4son alias show myfeature
658
+ p4 describe -s $(git p4son alias show)
659
+ ```
660
+
584
661
  #### alias new
585
662
 
586
663
  Save a changelist number under a named alias:
@@ -605,19 +682,24 @@ git p4son alias new 67890 myfeature -f
605
682
 
606
683
  #### alias delete
607
684
 
608
- Delete a changelist alias:
685
+ Delete a changelist alias, or all of them:
609
686
 
610
687
  ```sh
611
- git p4son alias delete [alias]
688
+ git p4son alias delete [alias | --all]
612
689
  ```
613
690
 
614
691
  **Arguments:**
615
692
  - `alias` (optional): Alias name to delete. Defaults to the current branch name.
616
693
 
694
+ **Options:**
695
+ - `--all`: Delete all aliases without prompting. Unlike `alias clean`, it does not ask first, which suits scripts
696
+ and AI agents
697
+
617
698
  **Examples:**
618
699
  ```sh
619
700
  git p4son alias delete # delete alias for current branch
620
701
  git p4son alias delete myfeature
702
+ git p4son alias delete --all
621
703
  ```
622
704
 
623
705
  #### alias clean
@@ -694,10 +776,19 @@ git-p4son completion <shell> [--dirname]
694
776
 
695
777
  See [Shell Completions](#shell-completions) below for installation instructions.
696
778
 
779
+ ### Skill Command
780
+
781
+ Install or show the [Claude Code skill](#claude-code-skill):
782
+
783
+ ```sh
784
+ git p4son skill install # install the skill for your user
785
+ git p4son skill show # print the instructions the skill gives to AI agents
786
+ ```
787
+
697
788
  ### The `branch` keyword
698
789
 
699
790
  Most commands that accept an alias or changelist argument default to the current branch name. You can also pass the
700
- `branch` keyword explicitly — it resolves to an alias name derived from the current git branch.
791
+ `branch` keyword explicitly - it resolves to an alias name derived from the current git branch.
701
792
 
702
793
  The keyword cannot be used in a detached HEAD state. Use `--no-alias` (on `new` and `review`) or supply an
703
794
  explicit alias name instead.
@@ -735,6 +826,30 @@ before the first sync.
735
826
  After a successful `git-p4son sync` that actually performs sync work, git-p4son runs executable hooks from
736
827
  `.git-p4son/hooks/post-sync/`.
737
828
 
829
+ ## Claude Code Skill
830
+
831
+ git-p4son ships a skill for Claude Code that teaches it how git-p4son is meant to be used: keeping `main` in step
832
+ with Perforce, never submitting on your behalf, creating reviews with full control of the changelist description,
833
+ updating them after feedback, and cleaning up after a submit. With it installed, you can
834
+ ask Claude to sync, put a branch up for review or address review feedback, and it will use git-p4son to do it.
835
+
836
+ Install it once for your user:
837
+
838
+ ```sh
839
+ git p4son skill install
840
+ ```
841
+
842
+ This writes `~/.claude/skills/git-p4son/SKILL.md` (under `$CLAUDE_CONFIG_DIR` if set). `init` offers to do the same.
843
+ The skill is installed for your user rather than in the workspace, where it would show up as an untracked file and
844
+ block `sync`, `new` and `update`.
845
+
846
+ The installed file is only a short stub: it tells Claude when the skill applies and to run `git p4son skill show`,
847
+ which prints the full instructions from the installed git-p4son. So the instructions always match your version of
848
+ git-p4son, and upgrading with pip needs no reinstall. Run `git p4son skill show` yourself to read what Claude is told.
849
+
850
+ Claude picks the skill up on its own when you work in a git-p4son workspace. You can also invoke it directly with
851
+ `/git-p4son`.
852
+
738
853
  ## Shell Completions
739
854
 
740
855
  Tab completion is available for bash, zsh, and PowerShell, including commands, flags, and dynamic alias names.