cherrypick-interactive 1.8.0 โ†’ 1.8.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.
Files changed (3) hide show
  1. package/README.md +178 -260
  2. package/package.json +1 -1
  3. package/src/tui/html.js +1 -1
package/README.md CHANGED
@@ -1,302 +1,220 @@
1
- # ๐Ÿชถ cherrypick-interactive
1
+ # cherrypick-interactive
2
2
 
3
- ### Cherry-pick missing commits from `dev` to `main` โ€” interactively and safely.
3
+ Cherry-pick missing commits from one branch to another โ€” interactively and safely.
4
4
 
5
- ---
5
+ ## What it does
6
6
 
7
- ## ๐Ÿšง Motivation
8
-
9
- When you maintain long-lived branches like `dev` and `main`, keeping them in sync can get messy.
10
- Sometimes you rebase, sometimes you cherry-pick, sometimes you merge release branches โ€” and every time, it's easy to lose track of which commits actually made it into production.
11
-
12
- **This CLI solves that pain point:**
13
-
14
- - It compares two branches (e.g. `origin/dev` vs `origin/main`)
15
- - Lists commits in `dev` that are *not yet* in `main`
16
- - Lets you choose which ones to cherry-pick interactively
17
- - Handles merge conflicts with an interactive resolution wizard
18
- - Preserves original commit messages perfectly (even with squashed commits)
19
- - (Optionally) bumps your semantic version, creates a release branch, updates `package.json`, and opens a GitHub draft PR for review
20
-
21
- No manual `git log` diffing. No risky merges. No guesswork.
22
-
23
- ---
24
-
25
- ## ๐Ÿงญ What it does
26
-
27
- - ๐Ÿ” Finds commits in `dev` not present in `main`
28
- - ๐Ÿ—‚๏ธ Lets you select which commits to cherry-pick (or pick all)
29
- - ๐Ÿชœ Cherry-picks in the correct order (oldest โ†’ newest)
30
- - โš”๏ธ **Interactive conflict resolution wizard** with multiple strategies
31
- - ๐ŸŽฏ **Preserves exact commit messages** from squashed commits
32
- - ๐Ÿช„ Detects **semantic version bump** (`major`, `minor`, `patch`) from conventional commits
33
- - ๐Ÿงฉ Creates a `release/x.y.z` branch from `main`
34
- - ๐Ÿงพ Generates a Markdown changelog from commits
35
- - ๐Ÿงฐ Optionally:
36
- - updates `package.json` version
37
- - commits and pushes it
38
- - opens a **GitHub PR** (draft or normal)
39
-
40
- ---
41
-
42
- ## ๐Ÿ“ฆ Installation
7
+ Compares two branches, shows what's missing, lets you pick which commits to move over, and handles the rest: conflicts, versioning, changelog, PR.
43
8
 
44
9
  ```bash
45
- npm install -g cherrypick-interactive
10
+ npx cherrypick-interactive
46
11
  ```
47
12
 
48
- (You can also run it directly without installing globally using `npx`.)
49
-
50
- ---
51
-
52
- ## ๐Ÿš€ Quick Start
13
+ ## Install
53
14
 
54
15
  ```bash
55
- cherrypick-interactive \
56
- --semantic-versioning \
57
- --version-file ./package.json \
58
- --create-release \
59
- --push-release \
60
- --draft-pr
16
+ npm install -g cherrypick-interactive
61
17
  ```
62
18
 
63
- โœ… This will:
64
- 1. Fetch `origin/dev` and `origin/main`
65
- 2. List commits in `dev` missing from `main`
66
- 3. Let you select which to cherry-pick
67
- 4. Compute the next version from commit messages
68
- 5. Create `release/<next-version>` from `main`
69
- 6. Cherry-pick the selected commits (with conflict resolution if needed)
70
- 7. Update your `package.json` version and commit it
71
- 8. Push the branch and open a **draft PR** on GitHub
72
-
73
- ---
74
-
75
- ## ๐Ÿงฉ Common Use Cases
76
-
77
- ### 1. Compare branches manually
19
+ ## Quick Start
78
20
 
79
21
  ```bash
22
+ # Interactive selection with all defaults
80
23
  cherrypick-interactive
81
- ```
82
-
83
- Lists commits in `origin/dev` that aren't in `origin/main`, filtered by the last week.
84
24
 
85
- ### 2. Cherry-pick all missing commits automatically
86
-
87
- ```bash
88
- cherrypick-interactive --all-yes
89
- ```
90
-
91
- ### 3. Preview changes without applying them
92
-
93
- ```bash
25
+ # Preview without applying
94
26
  cherrypick-interactive --dry-run
95
- ```
96
-
97
- ### 4. Filter commits by pattern
98
-
99
- ```bash
100
- cherrypick-interactive --ignore-commits "^chore\(deps\)|^ci:"
101
- ```
102
27
 
103
- Excludes commits starting with `chore(deps)` or `ci:` from the selection list.
104
-
105
- ### 5. Ignore certain commits from semantic versioning
106
-
107
- ```bash
108
- cherrypick-interactive --ignore-semver "bump|dependencies"
28
+ # Pick everything, no prompts
29
+ cherrypick-interactive --all-yes
109
30
  ```
110
31
 
111
- Treats commits containing "bump" or "dependencies" as chores (no version bump).
112
-
113
- ---
114
-
115
- ## โš™๏ธ Options
116
-
117
- | Flag | Description | Default |
118
- |------|--------------|----------|
119
- | `--dev` | Source branch (commits to copy) | `origin/dev` |
120
- | `--main` | Target branch (commits already merged here will be skipped) | `origin/main` |
121
- | `--since` | Git time window filter (e.g. `"2 weeks ago"`) | `1 week ago` |
122
- | `--no-fetch` | Skip `git fetch --prune` | `false` |
123
- | `--all-yes` | Cherry-pick all missing commits without prompt | `false` |
124
- | `--dry-run` | Show what would happen without applying changes | `false` |
125
- | `--semantic-versioning` | Detect semantic version bump from commits | `true` |
126
- | `--current-version` | Current version (if not reading from file) | โ€” |
127
- | `--version-file` | Path to `package.json` (to read & update version) | `./package.json` |
128
- | `--create-release` | Create `release/x.y.z` branch from `main` | `true` |
129
- | `--push-release` | Push release branch to origin | `true` |
130
- | `--draft-pr` | Create the GitHub PR as a draft | `false` |
131
- | `--version-commit-message` | Template for version bump commit | `chore(release): bump version to {{version}}` |
132
- | `--ignore-semver` | Comma-separated regex patterns to ignore for semver | โ€” |
133
- | `--ignore-commits` | Comma-separated regex patterns to exclude commits | โ€” |
134
-
135
- ---
136
-
137
- ## ๐Ÿง  How Semantic Versioning Works
138
-
139
- The tool analyzes commit messages using **Conventional Commits**:
140
-
141
- | Prefix | Example | Bump |
142
- |---------|----------|------|
143
- | `BREAKING CHANGE:` | `feat(auth): BREAKING CHANGE: require MFA` | **major** |
144
- | `feat:` | `feat(ui): add dark mode` | **minor** |
145
- | `fix:` / `perf:` | `fix(api): correct pagination offset` | **patch** |
146
-
147
- Use `--ignore-semver` to treat certain commits as chores:
32
+ Full workflow with release branch and PR:
148
33
 
149
34
  ```bash
150
- cherrypick-interactive --ignore-semver "^chore\(deps\)|bump|merge"
35
+ cherrypick-interactive \
36
+ --semantic-versioning \
37
+ --version-file ./package.json \
38
+ --create-release \
39
+ --push-release \
40
+ --draft-pr
151
41
  ```
152
42
 
153
- ---
154
-
155
- ## โš”๏ธ Interactive Conflict Resolution
156
-
157
- When cherry-picking encounters conflicts, the tool provides an **interactive wizard**:
158
-
159
- ### Conflict Resolution Options:
160
-
161
- **Per-file resolution:**
162
- - **Use ours** โ€” Keep the current branch's version
163
- - **Use theirs** โ€” Accept the cherry-picked commit's version
164
- - **Open in editor** โ€” Manually resolve conflicts in your editor
165
- - **Show diff** โ€” View the conflicting changes
166
- - **Mark resolved** โ€” Stage the file as-is
167
-
168
- **Bulk actions:**
169
- - **Use ours for ALL** โ€” Apply current branch's version to all conflicts
170
- - **Use theirs for ALL** โ€” Accept cherry-picked version for all conflicts
171
- - **Stage ALL** โ€” Mark all files as resolved
172
- - **Launch mergetool** โ€” Use Git's configured merge tool
173
-
174
- ### Key Features:
175
-
176
- โœ… **Preserves original commit messages** โ€” Even when resolving conflicts, the commit message from the original commit in `dev` is maintained exactly
177
- โœ… **Handles squashed commits** โ€” Works correctly with squashed commits that contain multiple changes
178
- โœ… **Resume cherry-picking** โ€” After resolving conflicts, automatically continues with remaining commits
179
-
180
- ---
181
-
182
- ## ๐Ÿงน Why This Helps
183
-
184
- If your team:
185
- - Rebases or cherry-picks from `dev` โ†’ `main`
186
- - Uses temporary release branches
187
- - Works with squashed commits
188
- - Needs to handle merge conflicts gracefully
189
- - Tracks semantic versions via commits
190
-
191
- โ€ฆthis CLI saves time and reduces errors.
192
- It automates a tedious, error-prone manual process into a single command that behaves like `yarn upgrade-interactive`, but for Git commits.
193
-
194
- **Special features:**
195
- - โœ… Preserves exact commit messages (critical for squashed commits)
196
- - โœ… Interactive conflict resolution without leaving the terminal
197
- - โœ… Smart pattern-based filtering for commits and version detection
198
- - โœ… Automatic changelog generation
199
-
200
- ---
201
-
202
- ## ๐Ÿงฐ Requirements
203
-
204
- - Node.js โ‰ฅ 18
205
- - Git โ‰ฅ 2.0
206
- - **GitHub CLI (`gh`)** โ€” *Optional, only required if using `--push-release`*
207
- - Install from: https://cli.github.com/
208
- - The tool will check if `gh` is installed and offer to continue without it
209
- - A clean working directory (no uncommitted changes)
210
-
211
- ---
212
-
213
- ## ๐ŸŽฏ Best Practices
214
-
215
- ### 1. Use `--ignore-commits` to filter noise
216
-
217
- ```bash
218
- cherrypick-interactive --ignore-commits "^ci:|^chore\(deps\):|Merge branch"
43
+ ## Features
44
+
45
+ **Core:**
46
+ - Finds commits in source branch not present in target branch
47
+ - Interactive commit selection (TUI dashboard or simple checkbox)
48
+ - Cherry-picks in correct order (oldest to newest)
49
+ - Interactive conflict resolution wizard (per-file or bulk)
50
+ - Preserves original commit messages
51
+
52
+ **Versioning & Release:**
53
+ - Detects semantic version bump from conventional commits
54
+ - Creates `release/x.y.z` branch
55
+ - Generates markdown changelog
56
+ - Updates `package.json` version
57
+ - Opens GitHub PR (draft or normal)
58
+
59
+ **Profiles:**
60
+ - Save and reuse CLI flag combinations
61
+ - `--save-profile hotfix` saves current flags
62
+ - `--profile hotfix` loads them back
63
+ - `--list-profiles` shows available profiles
64
+ - Stored in `.cherrypickrc.json`
65
+
66
+ **Tracker Integration:**
67
+ - Links ticket IDs in changelog to your issue tracker
68
+ - Built-in presets: `--tracker clickup`, `--tracker jira`, `--tracker linear`
69
+ - Custom patterns: `--ticket-pattern "#([a-z0-9]+)" --tracker-url "https://app.clickup.com/t/{{id}}"`
70
+ - ReDoS-safe regex validation
71
+
72
+ **CI Mode:**
73
+ - `--ci` for fully non-interactive execution
74
+ - `--conflict-strategy ours|theirs|skip|fail`
75
+ - `--format json` for structured output (stdout=JSON, stderr=logs)
76
+ - Distinct exit codes: 0=success, 1=conflict, 2=no commits, 3=auth error, 4=dependency
77
+
78
+ **Dependency Detection:**
79
+ - Warns when selected commits depend on unselected ones (file-level heuristic)
80
+ - Options: include missing commits, go back to selection, or continue anyway
81
+ - `--dependency-strategy warn|fail|ignore`
82
+
83
+ **Undo / Rollback:**
84
+ - `--undo` resets release branch to pre-cherry-pick state
85
+ - Checkpoint saved automatically before each session
86
+ - Validates branch integrity before reset
87
+ - Uses `--force-with-lease` (not `--force`)
88
+
89
+ **Changelog Preview:**
90
+ - Shows full changelog before cherry-pick starts
91
+ - Includes version bump info and ticket links
92
+ - Confirmation defaults to No โ€” must explicitly approve
93
+
94
+ ## Options
95
+
96
+ ### Cherry-pick
97
+
98
+ | Flag | Default | Description |
99
+ |------|---------|-------------|
100
+ | `--dev` | `origin/dev` | Source branch |
101
+ | `--main` | `origin/main` | Target branch |
102
+ | `--since` | `1 week ago` | Time window for commits |
103
+ | `--no-fetch` | `false` | Skip `git fetch --prune` |
104
+ | `--all-yes` | `false` | Select all commits without prompt |
105
+ | `--ignore-commits` | โ€” | Regex patterns to exclude commits |
106
+
107
+ ### Version
108
+
109
+ | Flag | Default | Description |
110
+ |------|---------|-------------|
111
+ | `--semantic-versioning` | `true` | Auto-detect version bump |
112
+ | `--current-version` | โ€” | Current X.Y.Z version |
113
+ | `--version-file` | `./package.json` | Read/write version from file |
114
+ | `--version-commit-message` | `chore(release): bump version to {{version}}` | Commit message template |
115
+ | `--ignore-semver` | โ€” | Regex patterns to exclude from versioning |
116
+
117
+ ### Release
118
+
119
+ | Flag | Default | Description |
120
+ |------|---------|-------------|
121
+ | `--create-release` | `true` | Create release branch |
122
+ | `--push-release` | `true` | Push and create PR |
123
+ | `--draft-pr` | `false` | Create PR as draft |
124
+
125
+ ### CI
126
+
127
+ | Flag | Default | Description |
128
+ |------|---------|-------------|
129
+ | `--ci` | `false` | Non-interactive mode |
130
+ | `--conflict-strategy` | `fail` | `fail`, `ours`, `theirs`, `skip` |
131
+ | `--format` | `text` | `text` or `json` |
132
+ | `--dependency-strategy` | `warn` | `warn`, `fail`, `ignore` |
133
+
134
+ ### Tracker
135
+
136
+ | Flag | Default | Description |
137
+ |------|---------|-------------|
138
+ | `--tracker` | โ€” | Preset: `clickup`, `jira`, `linear` |
139
+ | `--ticket-pattern` | โ€” | Custom regex (one capture group) |
140
+ | `--tracker-url` | โ€” | URL template with `{{id}}` |
141
+
142
+ ### Profile
143
+
144
+ | Flag | Default | Description |
145
+ |------|---------|-------------|
146
+ | `--profile` | โ€” | Load named profile |
147
+ | `--save-profile` | โ€” | Save current flags as profile |
148
+ | `--list-profiles` | `false` | List profiles and exit |
149
+
150
+ ### Session
151
+
152
+ | Flag | Default | Description |
153
+ |------|---------|-------------|
154
+ | `--undo` | `false` | Rollback to pre-cherry-pick state |
155
+
156
+ ### UI
157
+
158
+ | Flag | Default | Description |
159
+ |------|---------|-------------|
160
+ | `--no-tui` | `false` | Use simple checkbox instead of TUI |
161
+ | `--dry-run` | `false` | Preview without applying |
162
+
163
+ ## CI/CD Usage
164
+
165
+ ```yaml
166
+ - run: npx cherrypick-interactive --ci --conflict-strategy theirs --format json > result.json
219
167
  ```
220
168
 
221
- Exclude CI updates, dependency bumps, and merge commits from selection.
169
+ Exit codes: `0` success, `1` conflict, `2` no commits, `3` auth error, `4` dependency issue.
222
170
 
223
- ### 2. Use `--ignore-semver` for version accuracy
171
+ ## Profiles
224
172
 
225
173
  ```bash
226
- cherrypick-interactive --ignore-semver "bump|dependencies|merge"
227
- ```
174
+ # Save
175
+ cherrypick-interactive --save-profile hotfix --dev origin/develop --main origin/release --since "2 weeks ago"
228
176
 
229
- Prevent certain commits from affecting semantic version calculation.
177
+ # Use
178
+ cherrypick-interactive --profile hotfix
230
179
 
231
- ### 3. Always use `--draft-pr` for review
232
-
233
- ```bash
234
- cherrypick-interactive --draft-pr
180
+ # Override
181
+ cherrypick-interactive --profile hotfix --since "3 days ago"
235
182
  ```
236
183
 
237
- Creates draft PRs so your team can review before merging.
238
-
239
- ### 4. Test with `--dry-run` first
240
-
241
- ```bash
242
- cherrypick-interactive --dry-run
184
+ Config stored in `.cherrypickrc.json`:
185
+
186
+ ```json
187
+ {
188
+ "profiles": {
189
+ "hotfix": {
190
+ "dev": "origin/develop",
191
+ "main": "origin/release",
192
+ "since": "2 weeks ago"
193
+ }
194
+ },
195
+ "tracker": {
196
+ "ticket-pattern": "#([a-z0-9]+)",
197
+ "tracker-url": "https://app.clickup.com/t/{{id}}"
198
+ }
199
+ }
243
200
  ```
244
201
 
245
- See what would happen without making any changes.
246
-
247
- ---
248
-
249
- ## ๐Ÿงพ License
250
-
251
- **MIT** โ€” free to use, modify, and distribute.
202
+ ## Conflict Resolution
252
203
 
253
- ---
204
+ When conflicts occur, the tool offers:
254
205
 
255
- ## ๐Ÿง‘โ€๐Ÿ’ป Contributing
206
+ **Per-file:** use ours, use theirs, open in editor, show diff, mark resolved
256
207
 
257
- 1. Clone the repo
258
- 2. Run locally:
259
- ```bash
260
- node cli.js --dry-run
261
- ```
262
- 3. Test edge cases before submitting PRs:
263
- - Squashed commits with conflicts
264
- - Empty cherry-picks
265
- - Multiple conflict resolutions
266
- 4. Please follow Conventional Commits for your changes.
208
+ **Bulk:** use ours for all, use theirs for all, stage all, launch mergetool
267
209
 
268
- ---
210
+ In CI mode, `--conflict-strategy` handles this automatically.
269
211
 
270
- ## ๐Ÿ› Troubleshooting
212
+ ## Requirements
271
213
 
272
- ### "GitHub CLI (gh) is not installed"
273
- The tool automatically checks for `gh` CLI when using `--push-release`. If not found, you'll be prompted to:
274
- - Install it from https://cli.github.com/ and try again
275
- - Or continue without creating a PR (the release branch will still be pushed)
276
-
277
- You can also run without `--push-release` to skip PR creation entirely:
278
- ```bash
279
- cherrypick-interactive --create-release --no-push-release
280
- ```
281
-
282
- ### "Cherry-pick has conflicts"
283
- Use the interactive wizard to resolve conflicts file-by-file or in bulk.
284
-
285
- ### "Commit message changed after conflict resolution"
286
- This issue has been fixed! The tool now preserves the original commit message using `git commit -C <hash>`.
287
-
288
- ### "Version not detected correctly"
289
- Use `--ignore-semver` to exclude commits that shouldn't affect versioning:
290
- ```bash
291
- cherrypick-interactive --ignore-semver "bump|chore\(deps\)"
292
- ```
293
-
294
- ### "Too many commits to review"
295
- Use `--ignore-commits` to filter out noise, or adjust `--since` to a shorter time window:
296
- ```bash
297
- cherrypick-interactive --since "3 days ago" --ignore-commits "^ci:|^docs:"
298
- ```
214
+ - Node.js >= 20
215
+ - Git >= 2.0
216
+ - GitHub CLI (`gh`) โ€” optional, for `--push-release`
299
217
 
300
- ---
218
+ ## License
301
219
 
302
- > Created to make release management simpler and safer for teams who value clean Git history, predictable deployments, and efficient conflict resolution.
220
+ MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cherrypick-interactive",
3
- "version": "1.8.0",
3
+ "version": "1.8.1",
4
4
  "description": "Interactively cherry-pick commits that are in dev but not in main, using subject-based comparison.",
5
5
  "main": "cli.js",
6
6
  "bin": "cli.js",
package/src/tui/html.js CHANGED
@@ -1,4 +1,4 @@
1
- import { createElement } from 'ink';
1
+ import { createElement } from 'react';
2
2
  import htm from 'htm';
3
3
 
4
4
  export const html = htm.bind(createElement);