@codragraph/cli 1.6.4 → 2.0.0

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 (61) hide show
  1. package/README.md +34 -0
  2. package/dist/cli/analyze.d.ts +22 -0
  3. package/dist/cli/analyze.js +107 -4
  4. package/dist/cli/compress-stats.d.ts +29 -0
  5. package/dist/cli/compress-stats.js +97 -0
  6. package/dist/cli/graphstore.d.ts +6 -2
  7. package/dist/cli/graphstore.js +24 -2
  8. package/dist/cli/index.js +16 -2
  9. package/dist/cli/profile-heap.d.ts +35 -0
  10. package/dist/cli/profile-heap.js +126 -0
  11. package/dist/cli/setup.d.ts +13 -0
  12. package/dist/cli/setup.js +22 -11
  13. package/dist/cli/skill-gen.d.ts +14 -2
  14. package/dist/cli/skill-gen.js +52 -19
  15. package/dist/cli/tool.js +4 -0
  16. package/dist/core/embeddings/embedding-pipeline.js +24 -7
  17. package/dist/core/group/bridge-db.js +111 -24
  18. package/dist/core/lbug/content-read.d.ts +46 -0
  19. package/dist/core/lbug/content-read.js +64 -0
  20. package/dist/core/lbug/csv-generator.d.ts +2 -6
  21. package/dist/core/lbug/csv-generator.js +45 -12
  22. package/dist/core/lbug/lbug-adapter.d.ts +4 -1
  23. package/dist/core/lbug/lbug-adapter.js +153 -21
  24. package/dist/core/lbug/schema.d.ts +7 -7
  25. package/dist/core/lbug/schema.js +18 -0
  26. package/dist/core/run-analyze.d.ts +13 -0
  27. package/dist/core/run-analyze.js +91 -4
  28. package/dist/core/search/bm25-index.js +67 -15
  29. package/dist/mcp/local/local-backend.js +22 -5
  30. package/dist/server/api.js +4 -3
  31. package/dist/storage/repo-manager.d.ts +39 -0
  32. package/dist/storage/repo-manager.js +19 -0
  33. package/hooks/claude/codragraph-hook.cjs +95 -2
  34. package/package.json +4 -4
  35. package/scripts/build-tree-sitter-proto.cjs +15 -3
  36. package/scripts/patch-tree-sitter-swift.cjs +17 -4
  37. package/skills/codragraph-api-surface.md +110 -0
  38. package/skills/codragraph-config-audit.md +146 -0
  39. package/skills/codragraph-cross-repo-impact.md +135 -0
  40. package/skills/codragraph-data-lineage.md +137 -0
  41. package/skills/codragraph-dead-code.md +119 -0
  42. package/skills/codragraph-gh-actions-debug.md +162 -0
  43. package/skills/codragraph-gh-issue-workflow.md +178 -0
  44. package/skills/codragraph-gh-pr-workflow.md +176 -0
  45. package/skills/codragraph-gh-release-workflow.md +187 -0
  46. package/skills/codragraph-git-bisect.md +176 -0
  47. package/skills/codragraph-git-force-push.md +147 -0
  48. package/skills/codragraph-git-history-rewrite.md +174 -0
  49. package/skills/codragraph-git-rebase-vs-merge.md +138 -0
  50. package/skills/codragraph-git-recovery.md +181 -0
  51. package/skills/codragraph-git-worktree.md +145 -0
  52. package/skills/codragraph-migration-tracking.md +130 -0
  53. package/skills/codragraph-notebook-context.md +136 -0
  54. package/skills/codragraph-observability-coverage.md +125 -0
  55. package/skills/codragraph-onboarding.md +129 -0
  56. package/skills/codragraph-perf-hotspots.md +132 -0
  57. package/skills/codragraph-project-switcher.md +116 -0
  58. package/skills/codragraph-security-audit.md +144 -0
  59. package/skills/codragraph-sql-tracing.md +122 -0
  60. package/skills/codragraph-supply-chain-audit.md +153 -0
  61. package/skills/codragraph-test-coverage.md +97 -0
@@ -0,0 +1,176 @@
1
+ ---
2
+ name: codragraph-git-bisect
3
+ description: "Use when hunting a regression — narrowing down which commit introduced a bug across N commits using binary search. Covers manual bisect, automated bisect with a test script, and how to combine bisect with CodraGraph context to understand the bad commit. Examples: \"find which commit broke X\", \"git bisect\", \"regression hunt\", \"automated bisect\""
4
+ ---
5
+
6
+ # Regression Hunting with `git bisect`
7
+
8
+ ## When to Use
9
+
10
+ - "Tests pass at commit A but fail at commit B — which commit broke it?"
11
+ - "Performance regressed somewhere in the last 200 commits."
12
+ - "Find the commit that introduced this bug."
13
+ - "Automate a bisect with my test suite."
14
+
15
+ ## The principle
16
+
17
+ Bisect performs binary search over the commit graph. Given a
18
+ known-good commit (`good`) and a known-bad commit (`bad`), it picks the
19
+ midpoint, you mark it, and it halves the search space until exactly one
20
+ commit is identified. Log₂(N) tests instead of N.
21
+
22
+ ## Manual workflow
23
+
24
+ ```bash
25
+ # Start
26
+ git bisect start
27
+ git bisect bad <known-bad> # often HEAD or a commit/tag
28
+ git bisect good <known-good> # something older that worked
29
+
30
+ # Now git checks out the midpoint. Test it.
31
+ # Mark each midpoint:
32
+ git bisect bad # if the bug IS present
33
+ git bisect good # if the bug is NOT present
34
+ git bisect skip # if the commit can't be tested
35
+ # (won't compile, broken in some other way)
36
+
37
+ # Bisect narrows down. Repeat marking until git announces:
38
+ # → "<sha> is the first bad commit"
39
+
40
+ # Done — back to your starting state:
41
+ git bisect reset
42
+ ```
43
+
44
+ ## Automated workflow
45
+
46
+ If you have a script that exits 0 on good and non-zero on bad, you can
47
+ fully automate:
48
+
49
+ ```bash
50
+ git bisect start HEAD <known-good>
51
+ git bisect run ./scripts/repro-bug.sh
52
+ # → bisect runs the script at each midpoint; marks good/bad automatically;
53
+ # announces the first bad commit when done
54
+ ```
55
+
56
+ The script's exit codes:
57
+
58
+ ```
59
+ exit 0 → mark as good
60
+ exit 1..124, → mark as bad
61
+ 126..127
62
+ exit 125 → mark as skip (can't test this commit)
63
+ exit 128+ → abort the bisect
64
+ ```
65
+
66
+ ## Test-script template
67
+
68
+ ```bash
69
+ #!/usr/bin/env bash
70
+ # scripts/repro-bug.sh — bisect-aware reproduction script
71
+ set -e
72
+
73
+ # 1. If this commit can't even build, skip it (don't say bad).
74
+ npm install --silent --no-audit > /dev/null 2>&1 || exit 125
75
+ npm run build > /dev/null 2>&1 || exit 125
76
+
77
+ # 2. Run the targeted test that demonstrates the bug.
78
+ if npx vitest run path/to/regression.test.ts --reporter=basic > /dev/null 2>&1; then
79
+ exit 0 # good
80
+ else
81
+ exit 1 # bad
82
+ fi
83
+ ```
84
+
85
+ ## Why CodraGraph helps here
86
+
87
+ Once bisect names the first bad commit, the next question is *why*
88
+ that commit broke things. CodraGraph's `diff --semantic` and `context`
89
+ tell you exactly what changed, structurally:
90
+
91
+ ```bash
92
+ git bisect log # see the bisection that found it
93
+ BAD=$(git bisect log | grep "first bad commit" | awk '{print $1}')
94
+
95
+ # What changed structurally between good and bad?
96
+ codragraph diff "$BAD"^ "$BAD" --semantic
97
+ # → addedAPIs / removedAPIs / classifiedModifications
98
+
99
+ # Get full context on the modified symbols
100
+ codragraph_context({name: "<symbol from the diff>"})
101
+ ```
102
+
103
+ This turns "commit X is bad" into "commit X removed/modified Y, which
104
+ broke flow Z." That's the actionable answer.
105
+
106
+ ## Bisect across non-linear history
107
+
108
+ If your history has merges, bisect handles them but the midpoints are
109
+ weird (commits from sibling branches). Two helpful flags:
110
+
111
+ ```bash
112
+ git bisect start --first-parent HEAD <known-good>
113
+ # → only follows the first-parent path (main line of merges).
114
+ # Useful when feature-branch commits aren't worth testing individually.
115
+
116
+ git bisect start --no-checkout HEAD <known-good>
117
+ # → don't checkout each midpoint; instead just sets BISECT_HEAD ref.
118
+ # Use when checkout is expensive (huge repo, slow build).
119
+ ```
120
+
121
+ ## Pitfalls
122
+
123
+ | Pitfall | What happens | Fix |
124
+ |---|---|---|
125
+ | Forgot to `bisect reset` after finishing | Stuck in detached state, future `git pull` weird | `git bisect reset` returns you to your branch |
126
+ | Test depends on uncommitted state | Bisect finds noise, not the real bug | Stash before bisecting; ensure script is self-contained |
127
+ | Build broken in middle of range | Every middle commit looks "bad" | Use `git bisect skip` or exit-code 125 in the auto script |
128
+ | Submodules not in sync | Wrong code being tested | Add `git submodule update --init --recursive` to the script |
129
+ | Found a "bad commit" that's a merge | Probably a transient issue or skip-worthy | Inspect the merge: `git show --first-parent <merge>` |
130
+
131
+ ## Checklist
132
+
133
+ ```
134
+ - [ ] Identified a clear known-good and known-bad commit
135
+ - [ ] Have a deterministic, single-command reproduction
136
+ - [ ] Repro is fast enough (<2 min ideally; bisect runs ~log₂(N) times)
137
+ - [ ] Build can complete on every commit in the range (or skip script handles it)
138
+ - [ ] Use `git bisect run <script>` for full automation
139
+ - [ ] After hit: codragraph diff <bad>^ <bad> --semantic to understand WHY
140
+ - [ ] git bisect reset before resuming work
141
+ ```
142
+
143
+ ## Example: "Tests started failing in the last 3 weeks"
144
+
145
+ ```bash
146
+ # 1. Confirm endpoints
147
+ git checkout main && npx vitest run path/to/regression.test.ts
148
+ # → fails
149
+
150
+ git checkout v1.5.3 # known-good 3 weeks ago
151
+ npx vitest run path/to/regression.test.ts
152
+ # → passes
153
+
154
+ # 2. Automate
155
+ git bisect start main v1.5.3
156
+ cat > /tmp/repro.sh <<'EOF'
157
+ #!/usr/bin/env bash
158
+ set -e
159
+ npm install --silent || exit 125
160
+ npx vitest run path/to/regression.test.ts --reporter=basic > /dev/null 2>&1
161
+ EOF
162
+ chmod +x /tmp/repro.sh
163
+ git bisect run /tmp/repro.sh
164
+ # → "abc1234 is the first bad commit"
165
+
166
+ # 3. Understand the bad commit
167
+ codragraph diff abc1234^ abc1234 --semantic
168
+ # → modified validateUser (parameter count 3→4)
169
+
170
+ codragraph_context({name: "validateUser"})
171
+ # → caller `loginFlow` still passes 3 args — that's the regression
172
+
173
+ # 4. Reset and fix
174
+ git bisect reset
175
+ # Patch the caller; tests pass; ship.
176
+ ```
@@ -0,0 +1,147 @@
1
+ ---
2
+ name: codragraph-git-force-push
3
+ description: "Use when the user is about to force-push, recovering after someone else force-pushed, or asking whether it's safe. Covers --force vs --force-with-lease, recovery from a bad force-push, and the rules for shared vs personal branches. Examples: \"force push\", \"is force push safe\", \"someone overwrote my work\", \"git push rejected\", \"--force-with-lease\""
4
+ ---
5
+
6
+ # Force Push — When, How, and Recovery
7
+
8
+ ## When to Use
9
+
10
+ - "Can I force push to this branch?"
11
+ - "Git is rejecting my push, is force the answer?"
12
+ - "Someone force-pushed and lost my commits — help."
13
+ - "What's the difference between --force and --force-with-lease?"
14
+
15
+ ## The rules
16
+
17
+ 1. **Never `--force` on a shared branch** without coordinating. You will
18
+ silently overwrite collaborators' commits. Their reflogs save them; their
19
+ patience does not.
20
+ 2. **Always prefer `--force-with-lease`** over `--force`. It refuses the
21
+ push if the remote has commits you haven't seen — i.e. someone pushed
22
+ while you were rebasing.
23
+ 3. **Never force on `main` / `master` / `release/*`** unless you're recovering
24
+ from a documented incident with explicit sign-off. Branch protection
25
+ should make this impossible; if it's possible, fix the protection rule.
26
+ 4. **Force-pushing your OWN feature branch** after a rebase is normal and
27
+ expected. Just use `--force-with-lease`.
28
+
29
+ ## Decision tree
30
+
31
+ ```
32
+ Is the branch protected on the remote?
33
+ ├─ yes → STOP. Don't force. Open a PR or get an admin to lift protection
34
+ │ for a documented operation.
35
+ └─ no → Is anyone else committing to this branch?
36
+ ├─ yes → STOP. Coordinate. They'll lose work if you force.
37
+ └─ no → Have you fetched the latest remote tip?
38
+ ├─ no → git fetch first, then `git push --force-with-lease`
39
+ └─ yes → `git push --force-with-lease` is safe.
40
+ ```
41
+
42
+ ## --force vs --force-with-lease
43
+
44
+ ```bash
45
+ # DANGEROUS: overwrites whatever is on the remote, no matter what.
46
+ git push --force
47
+
48
+ # SAFER: only succeeds if the remote tip matches what you last fetched.
49
+ # If anyone pushed in the meantime, this aborts.
50
+ git push --force-with-lease
51
+
52
+ # EVEN SAFER: explicitly require the remote SHA to be what you expect.
53
+ git push --force-with-lease=<branch>:<expected-sha>
54
+ ```
55
+
56
+ > Make `--force-with-lease` your default by aliasing:
57
+ > `git config --global alias.fwl 'push --force-with-lease'`
58
+
59
+ ## Recovery: someone force-pushed and lost your work
60
+
61
+ Your local clone has the original commits in its reflog. You haven't lost
62
+ anything as long as you haven't run `git gc --prune=now` AND your reflog
63
+ is still intact (default 90-day expiry).
64
+
65
+ ```bash
66
+ # 1. Find the lost commit on YOUR machine
67
+ git reflog show <branch>
68
+ # → look for "<branch>@{N}: ... before force push" or your last commit
69
+
70
+ # 2. Inspect it
71
+ git show <sha>
72
+ git log <sha> --oneline -20
73
+
74
+ # 3a. If they overwrote with rubbish: reset your branch to your old tip
75
+ # (this re-creates the divergence; coordinate before re-pushing)
76
+ git checkout <branch>
77
+ git reset --hard <sha-from-reflog>
78
+
79
+ # 3b. If they had legitimate changes you also want to keep: cherry-pick
80
+ # YOUR lost commits onto their version
81
+ git checkout <branch>
82
+ git pull # accept their version
83
+ git cherry-pick <your-lost-sha-1> <your-lost-sha-2> ...
84
+
85
+ # 4. Push back (with --force-with-lease to avoid the same problem)
86
+ git push --force-with-lease
87
+ ```
88
+
89
+ If the only copy of the lost commits was on the remote (no local clone),
90
+ the recovery options are:
91
+
92
+ - GitHub: contact GitHub Support — they retain dangling commits for ~30 days.
93
+ - Self-hosted GitLab/Gitea: server-side reflog (if enabled) or a backup.
94
+
95
+ ## Recovery: I force-pushed something I shouldn't have
96
+
97
+ If you JUST did it and have a terminal where the previous local state still
98
+ exists:
99
+
100
+ ```bash
101
+ git reflog # find the previous tip
102
+ git reset --hard <previous-sha>
103
+ git push --force-with-lease # restore the remote
104
+ ```
105
+
106
+ If you've already moved on locally:
107
+
108
+ ```bash
109
+ git fetch origin
110
+ git reflog show origin/<branch>
111
+ # → look for the line BEFORE the force push you just did
112
+ git reset --hard <recovered-sha>
113
+ git push --force-with-lease
114
+ ```
115
+
116
+ ## Why CodraGraph helps here
117
+
118
+ After a force-push (yours or theirs), `codragraph diff` against the
119
+ recovered SHA tells you EXACTLY what structural changes were undone or
120
+ reapplied — so you can verify nothing important got lost in the
121
+ recovery:
122
+
123
+ ```bash
124
+ codragraph diff <recovered-sha> HEAD --semantic
125
+ # If addedAPIs / removedAPIs reveals work that should still be present,
126
+ # the recovery is incomplete — go back to the reflog and pick more.
127
+ ```
128
+
129
+ ## Checklist (before any --force / --force-with-lease)
130
+
131
+ ```
132
+ - [ ] Branch is NOT protected on the remote
133
+ - [ ] Branch is NOT main / master / release/*
134
+ - [ ] You're the only one committing to it (git log <branch> | grep -c Author)
135
+ - [ ] You've git-fetched recently (so --force-with-lease has fresh info)
136
+ - [ ] Using --force-with-lease, NEVER bare --force
137
+ - [ ] If recovering: verified the recovered SHA via codragraph diff
138
+ ```
139
+
140
+ ## Pitfalls
141
+
142
+ | Pitfall | What goes wrong | Avoidance |
143
+ |---|---|---|
144
+ | `git push -f` on shared branch | collaborators' commits silently gone | --force-with-lease + check `git log <branch>` for other authors first |
145
+ | `--force-with-lease` after `git fetch` | lease check passes against the freshly-fetched tip — no protection | run lease BEFORE the fetch, or specify the expected SHA explicitly |
146
+ | Force-push during CI run | CI race conditions, half-deployed states | wait for CI to finish, then force |
147
+ | Forgetting reflog can save you | panic | reflogs default to 90 days; check `git reflog` before destroying anything |
@@ -0,0 +1,174 @@
1
+ ---
2
+ name: codragraph-git-history-rewrite
3
+ description: "Use when rewriting commit history — squashing WIP commits, splitting a fat commit, removing a leaked secret, changing author info, or running git filter-repo / BFG. Covers interactive rebase, fixup/autosquash, splitting commits, and the safety rules for rewriting public history. Examples: \"squash my commits\", \"clean up history\", \"remove a leaked secret from history\", \"split this commit\", \"git filter-repo\""
4
+ ---
5
+
6
+ # History Rewriting — Safely
7
+
8
+ ## When to Use
9
+
10
+ - "Squash my last 5 WIP commits before opening a PR."
11
+ - "Split this giant commit into 3 logical ones."
12
+ - "Remove a leaked secret from history."
13
+ - "Change the author of past commits."
14
+ - "Drop a commit from the middle of the branch."
15
+
16
+ ## The cardinal rule
17
+
18
+ **Never rewrite history that's been pushed to a shared branch.** Rewriting
19
+ public history breaks every clone that pulled it. For shared branches:
20
+ make a new commit that fixes/reverts the offending one. For your own
21
+ branch (or any branch you alone work on), rewrite freely with
22
+ `--force-with-lease`.
23
+
24
+ ## Interactive rebase
25
+
26
+ ```bash
27
+ git rebase -i origin/main # rebase your branch onto main, interactively
28
+ # OR rebase the last N commits without changing the base:
29
+ git rebase -i HEAD~N
30
+ ```
31
+
32
+ You get an editor with one line per commit:
33
+
34
+ ```
35
+ pick abc1234 wip: hack on auth
36
+ pick def5678 wip: more auth
37
+ pick fed9876 fix typo
38
+ pick 012abcd add real auth flow
39
+ ```
40
+
41
+ Change `pick` to one of:
42
+
43
+ | Command | Effect |
44
+ |---|---|
45
+ | `pick` | keep the commit as-is |
46
+ | `reword` | keep the changes, edit the message |
47
+ | `edit` | pause after applying so you can `git commit --amend` or split |
48
+ | `squash` | merge into previous commit, edit combined message |
49
+ | `fixup` | merge into previous commit, drop this commit's message |
50
+ | `drop` | remove the commit entirely (its changes are gone) |
51
+ | `exec <cmd>` | run a shell command after this commit (CI-style validation per commit) |
52
+
53
+ Reorder lines to reorder commits. Save and exit; rebase replays them.
54
+
55
+ ## Fixup + autosquash workflow (the cleanest pattern)
56
+
57
+ ```bash
58
+ # While developing, instead of "wip" commits, mark fixups against a target:
59
+ git commit --fixup=<sha-of-target-commit>
60
+
61
+ # At the end, squash all fixups in one go:
62
+ git rebase -i --autosquash origin/main
63
+ # → all `fixup!` commits are auto-placed and pre-marked. Just save.
64
+ ```
65
+
66
+ This produces a clean, atomic-commit branch ready to PR — no manual
67
+ reordering needed.
68
+
69
+ ## Splitting a fat commit
70
+
71
+ ```bash
72
+ git rebase -i <commit>^ # interactive rebase starting AT the fat commit
73
+ # Mark it `edit` and save.
74
+
75
+ # Now you're paused at the fat commit. Reset to its parent, keep the changes:
76
+ git reset HEAD^
77
+
78
+ # Stage and commit each logical chunk separately:
79
+ git add <files-for-part-1>
80
+ git commit -m "first logical part"
81
+ git add <files-for-part-2>
82
+ git commit -m "second logical part"
83
+ git add -A
84
+ git commit -m "third logical part"
85
+
86
+ # Resume the rebase:
87
+ git rebase --continue
88
+ ```
89
+
90
+ ## Removing a leaked secret from history
91
+
92
+ If a secret (API key, password, .env) was committed:
93
+
94
+ 1. **Rotate the secret first.** Once it's on a public remote, treat it as
95
+ leaked — even after history scrub.
96
+ 2. **Then scrub history with `git filter-repo`** (the modern replacement
97
+ for `filter-branch`):
98
+
99
+ ```bash
100
+ # Install: pip install git-filter-repo (or pipx)
101
+
102
+ # Remove a specific file from all history:
103
+ git filter-repo --invert-paths --path path/to/leaked.env
104
+
105
+ # Or remove a string/secret from blob contents:
106
+ echo 'sk_live_abc***123==>REDACTED' > /tmp/replacements.txt
107
+ git filter-repo --replace-text /tmp/replacements.txt
108
+
109
+ # After filter-repo, the remote is forcibly out of sync. Coordinate with the
110
+ # team and force-push:
111
+ git push --force-with-lease origin --all
112
+ git push --force-with-lease origin --tags
113
+ ```
114
+
115
+ Alternative: BFG (`https://rtyley.github.io/bfg-repo-cleaner/`) is
116
+ faster for large repos but more limited.
117
+
118
+ > **Important:** GitHub caches blobs even after force-push. The blob is
119
+ > still accessible by SHA URL for ~30 days unless you contact GitHub
120
+ > Support to purge. Treat the secret as compromised.
121
+
122
+ ## Changing author info on past commits
123
+
124
+ ```bash
125
+ # Most recent commit only:
126
+ git commit --amend --author="New Name <new@email>"
127
+
128
+ # Multiple commits with filter-repo:
129
+ git filter-repo --commit-callback '
130
+ if commit.author_email == b"old@email":
131
+ commit.author_email = b"new@email"
132
+ commit.author_name = b"New Name"
133
+ '
134
+ ```
135
+
136
+ ## Why CodraGraph helps here
137
+
138
+ After any history rewrite, the structural diff against the pre-rewrite
139
+ state proves you didn't accidentally drop or alter functional code:
140
+
141
+ ```bash
142
+ # Before rewrite: snapshot the structural state
143
+ codragraph commit -m "pre-rewrite snapshot"
144
+ git rebase -i origin/main # do the rewrite
145
+ codragraph analyze # re-index after
146
+
147
+ # Confirm structural equivalence (or see exactly what differs):
148
+ codragraph diff <pre-snapshot-id> HEAD --semantic
149
+ # → Should be empty if you only rewrote messages / order.
150
+ # → If addedAPIs / removedAPIs appear, the rewrite changed semantics.
151
+ ```
152
+
153
+ ## Pitfalls
154
+
155
+ | Pitfall | What goes wrong | Avoidance |
156
+ |---|---|---|
157
+ | Rewriting shared branch | Collaborators' clones diverge | Only rewrite local-or-personal branches |
158
+ | `drop` instead of `fixup` | Lost changes silently | Verify with `codragraph diff` after the rebase |
159
+ | Editing during rebase, forgetting `--continue` | Stuck in detached state | `git rebase --continue` after each manual step |
160
+ | `git rebase --abort` after edits | Loses your edits | Stash before rebase if you have uncommitted work |
161
+ | `filter-branch` (legacy) | Slow, error-prone, deprecated | Use `git filter-repo` |
162
+ | Force-pushing after secret scrub without rotation | Secret still compromised | Rotate FIRST, scrub SECOND |
163
+
164
+ ## Checklist before any history rewrite
165
+
166
+ ```
167
+ - [ ] Branch is NOT shared (or you have explicit team coordination)
168
+ - [ ] Snapshot pre-state with `codragraph commit -m "pre-rewrite"`
169
+ - [ ] Decide: interactive rebase (small) vs filter-repo (large/secrets)
170
+ - [ ] Run the rewrite
171
+ - [ ] Re-analyze + `codragraph diff` to verify no semantic surprises
172
+ - [ ] Push with --force-with-lease
173
+ - [ ] If secrets were involved: rotate FIRST, then scrub, then push
174
+ ```
@@ -0,0 +1,138 @@
1
+ ---
2
+ name: codragraph-git-rebase-vs-merge
3
+ description: "Use when deciding between rebase, merge, squash-merge, or rebase-and-merge for integrating a branch — both for local catch-up (pulling main into a feature branch) and for landing a PR. Examples: \"should I rebase or merge\", \"how do I integrate main into my branch\", \"squash vs rebase merge\", \"clean up my branch history before PR\""
4
+ ---
5
+
6
+ # Rebase vs Merge — A Decision Guide
7
+
8
+ ## When to Use
9
+
10
+ - "How do I bring main into my feature branch?"
11
+ - "Should I squash this PR or merge it?"
12
+ - "Should I rebase before pushing?"
13
+ - "Which merge strategy do I pick on the GitHub PR button?"
14
+ - Any time you have a branch and need to combine it with another.
15
+
16
+ ## The decision rule (read this first)
17
+
18
+ | Situation | Use | Why |
19
+ |---|---|---|
20
+ | Branch is **local-only**, you want it to track main | `git pull --rebase` or `git rebase main` | Keeps your local history linear; nothing has been shared yet |
21
+ | Branch is **shared** (already pushed, others may have pulled) | `git merge main` (or `--no-rebase`) | Rebase rewrites SHAs — collaborators' clones break |
22
+ | You're about to **open a PR** and want clean history | `git rebase -i main` (interactive) | Squash WIP commits, reword messages, end with N tidy commits |
23
+ | You're **landing a PR** with one logical change | **Squash-merge** on GitHub | One commit on main, clean log, PR description becomes the body |
24
+ | You're landing a PR with multiple **already-tidy** commits | **Rebase-and-merge** on GitHub | Preserves your atomic commits; no merge bubble |
25
+ | You're landing a long-running branch that **must show as a unit** | **Merge commit** on GitHub | Preserves the branch topology — useful for release branches |
26
+
27
+ If you remember nothing else: **rebase what's only yours, merge what's already shared.**
28
+
29
+ ## Workflow: catching up a feature branch
30
+
31
+ ```bash
32
+ # Local-only branch (fast-forward integration)
33
+ git fetch origin
34
+ git rebase origin/main # replays your commits on top of main
35
+
36
+ # Already pushed branch (avoid SHA churn for collaborators)
37
+ git fetch origin
38
+ git merge origin/main # creates a merge commit — collaborators stay in sync
39
+
40
+ # OR explicitly opt into rebase even on shared branches (coordinate first!)
41
+ git rebase origin/main
42
+ git push --force-with-lease # SEE codragraph-git-force-push skill
43
+ ```
44
+
45
+ ## Workflow: cleaning up before opening a PR
46
+
47
+ ```bash
48
+ git fetch origin
49
+ git rebase -i origin/main # interactive — squash, fixup, reword
50
+
51
+ # Common interactive-rebase actions:
52
+ # pick - keep commit
53
+ # reword - change message
54
+ # squash - merge into previous, edit combined message
55
+ # fixup - merge into previous, drop this message
56
+ # drop - remove the commit entirely
57
+ ```
58
+
59
+ ## Workflow: landing a PR (GitHub UI / `gh pr merge`)
60
+
61
+ ```bash
62
+ # Squash-merge — one logical change, one commit on main:
63
+ gh pr merge --squash --delete-branch
64
+
65
+ # Rebase-and-merge — preserve your N commits as N commits on main:
66
+ gh pr merge --rebase --delete-branch
67
+
68
+ # Merge commit — preserve the branch as a unit (rare; use for releases):
69
+ gh pr merge --merge --delete-branch
70
+ ```
71
+
72
+ ## Why CodraGraph helps here
73
+
74
+ The hardest part of choosing a strategy isn't the mechanics — it's
75
+ predicting whether your branch will conflict structurally with main.
76
+ CodraGraph's `diff --semantic` tells you exactly which APIs / signatures
77
+ changed on each side, so you can see *before* the merge whether your
78
+ branch and main both touched the same callgraph regions.
79
+
80
+ ```
81
+ codragraph diff main HEAD --semantic --json | jq '.semantic'
82
+ → added APIs / removed APIs / classified modifications on YOUR branch
83
+
84
+ codragraph diff <last-shared-ancestor> main --semantic --json | jq '.semantic'
85
+ → what main has done since you forked
86
+ ```
87
+
88
+ If both diffs touch overlapping symbols, prefer **merge** (preserves both
89
+ sides as branches you can reason about) over rebase (which re-writes your
90
+ side and may produce noisy conflicts).
91
+
92
+ ## Pitfalls
93
+
94
+ | Pitfall | Symptom | Fix |
95
+ |---|---|---|
96
+ | Rebasing a shared branch | Collaborators report "diverged history", lost commits | Merge instead; don't rebase shared branches without coordination |
97
+ | Squash-merge into long-running branch | Loses individual commit context | Use rebase-and-merge for branches that need history preserved |
98
+ | `git pull` without `--rebase` flag on a feature branch | Random merge bubbles in your branch | Set `git config --global pull.rebase true` or always `pull --rebase` on feature branches |
99
+ | Rebasing ON TOP of work in progress (uncommitted) | "Your local changes would be overwritten" | `git stash` first, rebase, `git stash pop` |
100
+
101
+ ## Checklist before merging a PR
102
+
103
+ ```
104
+ - [ ] CI green (lint, tests, typecheck)
105
+ - [ ] codragraph_detect_changes({scope: "compare", base_ref: "main"}) clean
106
+ - [ ] codragraph diff main HEAD --semantic — review removed APIs
107
+ - [ ] PR description matches the (would-be-squash) commit message
108
+ - [ ] Decided strategy: squash (single change) vs rebase-and-merge (multiple atomic) vs merge (release/topology)
109
+ - [ ] gh pr merge --squash --delete-branch (or appropriate flag)
110
+ ```
111
+
112
+ ## Example: "Should I rebase or merge main into my 4-day-old branch?"
113
+
114
+ ```
115
+ 1. Check if the branch is shared:
116
+ git config branch.<your-branch>.remote
117
+ → "origin" — yes, pushed.
118
+
119
+ 2. Check who else might have it:
120
+ gh api repos/{owner}/{repo}/pulls?head={your-branch} --jq '.[].user.login'
121
+ git log origin/<your-branch>..main --oneline | head
122
+ → no co-authors observed; just you and CI.
123
+
124
+ 3. Check structural conflict potential:
125
+ codragraph diff main <your-branch> --semantic
126
+ → 2 added APIs, 1 modified signature
127
+ codragraph diff <merge-base> main --semantic
128
+ → 0 changes touching the same files
129
+ → no structural conflict expected.
130
+
131
+ 4. Decision: rebase (it's effectively local) + force-with-lease.
132
+ git fetch origin
133
+ git rebase origin/main
134
+ # Resolve any conflicts file-by-file
135
+ git push --force-with-lease
136
+
137
+ 5. If structural conflict HAD been likely → merge, not rebase.
138
+ ```