Add Rebase Rules
SkillFiles & storageGenerates .rebase add/override/replace rules from a commit that changes code/ files, updates rebase.sh conflict routing, and appends .rebase/CHANGELOG.md. Use when asked to add rebasing rules for a commit or PR.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Add Rebase Rules skill
What this skill tells your AI
The instructions your AI receives, as published by che-incubator/che-code in .claude/skills/add-rebase-rules/SKILL.md and read by ahel’s review.
Create or update rebasing rules for Che-specific changes that touch VS Code subtree files under code/.
Use this skill when the user gives a commit SHA (or PR/commit URL) and asks to add rebasing rules.
Required input
- A commit SHA is expected in
$ARGUMENTS. - If
$ARGUMENTSis empty, ask the user for a commit SHA before proceeding.
Scope and exclusions
Only consider changed files under code/.
Never create rebasing rules for:
code/extensions/che-*/**- any
**/package-lock.json
Important:
- A file can be under
code/and still be Che-only (for examplecode/src/.../che/...newly created by Che). Do not create a rule for such files if they are not upstream VS Code files. - Still create rules for the upstream file(s) that import/use those Che-only helpers.
Workflow
-
Resolve the target commit and collect changed files
- If input is a URL, extract the SHA.
- Get changed files:
git show --name-only --pretty='' <sha> | sort -u
- Filter to the rule candidate set:
- include: files starting with
code/ - exclude:
code/extensions/che-*/** - exclude:
**/package-lock.json
- include: files starting with
-
Classify each candidate file
*/package.json-> JSON merge rule (.rebase/add/and/or.rebase/override/)- Other modified upstream files -> replace rule (
.rebase/replace/<path>.json) - Newly added Che-only files with no upstream counterpart -> skip (no rule needed)
-
Create or update JSON merge rules for
package.json- Preserve only minimal changed subtree (do not copy entire package.json).
- Use:
.rebase/add/<path>for new keys or additive nested values.rebase/override/<path>when overriding existing values must be explicit
- It is valid to use both for one file.
- Keep file formatting consistent with existing
.rebaseJSON style (2-space indentation). - Choosing add vs override for dependency version pins (e.g. CVE fixes):
- If the dependency already exists in the upstream
package.json(independencies,devDependencies, etc.) and we need a different version → use.rebase/override/with the correct section. This is an override of an existing upstream value. - If the fix uses npm
overrides(the npm feature that pins transitive dependency versions) and the override key does not exist in upstream'soverridessection → use.rebase/add/. This is additive content absent from upstream. - Prefer the JSON merge mechanism (add or override) over
.rebase/replace/forpackage.jsonchanges. However,.rebase/replace/is acceptable when the change cannot be expressed by JSON merge alone — for example, rewriting a dependency URL format (e.g. fixing a Git URL — see.rebase/replace/code/extensions/emmet/package.json.json) or inserting a new entry at a specific position among existing keys. - Place each entry in the file where the dependency actually lives in upstream. For example, if
@vitest/coverage-v8is a devDependency ofcode/extensions/copilot/package.json, its override rule belongs in.rebase/override/code/extensions/copilot/package.json, not in a sibling package.
- If the dependency already exists in the upstream
-
Create or update replace rules for non-JSON files
- File path:
.rebase/replace/<original-path>.json - Format: JSON array of objects with
fromandby. - Add one rule per changed hunk, using stable and unique snippets.
- Ensure
fromappears exactly once in the upstream file. Both sed and perl handlers replace all occurrences — iffrommatches multiple places, all will be replaced, which is almost always wrong. Extend the snippet with more surrounding context to make it unique. - Prefer the smallest safe snippet that is unlikely to change accidentally, but large enough to be unique in the file.
- If replacement is multiline, encode using escaped newlines/tabs in JSON consistently with existing files.
- For multiline
fromsnippets, start at the first non-whitespace token (avoid anchoring on leading indentation only). - Prefer replacing the whole logical block (
if (...) { ... }) rather than only an inner line fragment, so closing braces remain structurally correct. - Encode special characters correctly for the handler used in
rebase.sh. See the encoding tables below.
- File path:
Sed encoding (apply_changes)
Values go through: JSON parse → jq -r → escape_litteral → sed.
| Character in target | from encoding | by encoding |
|---|---|---|
| Newline | \\\n | \\\n |
| Tab | \\\t | \\\t |
& | literal | \\& |
* | \\* | literal |
$, [, ] | literal (escape_litteral handles) | literal |
" | \\\" | \\\" |
Common pitfall — & in sed by values: In sed replacement strings, & means "the entire matched text". Writing && in a by value produces the matched from text repeated twice instead of a literal &&. Always escape as \\&\\&. This applies to any & in by, not just &&.
Perl encoding (apply_changes_multi_line / apply_multi_line_replace)
Values go through: JSON parse → jq -r → env var → perl \Q\E (from) / literal (by).
| Character in target | from encoding | by encoding |
|---|---|---|
| Newline | \n | \n |
| Tab | \t | \t |
| Any special char | literal | literal |
Prefer multiline (perl) for new rules — simpler encoding, handles all cases, no & pitfall.
-
Update
rebase.shconflict routing- Ensure each file that now has a new rebasing rule is routable in
resolve_conflicts. - For
package.jsonfiles:- add
elifbranch callingapply_package_changes_by_path "$conflictingFile"(or equivalent existing pattern).
- add
- For non-JSON replace rules:
- use
apply_changes "$conflictingFile"for line-based replacements. - For multiline replacements,
rebase.shhas two handlers — do not always default to one:apply_changes_multi_line "$conflictingFile"— higher-level wrapper that resets the file (git checkout --theirs), callsapply_multi_line_replace, then stages the result (git add).apply_multi_line_replace "$conflictingFile"— low-level function that performs the Perl multiline replacement directly, without git checkout/add.
- Before adding a routing branch, inspect the existing
resolve_conflictsblock inrebase.shand look at how other files in the same area are routed. Match the handler already used for similar files. For example, if neighboring entries callapply_multi_line_replacedirectly, use that; if they useapply_changes_multi_line, use that instead.
- use
- Do not add duplicate branches.
- Ensure each file that now has a new rebasing rule is routable in
-
Update
.rebase/CHANGELOG.md- Append a new entry in existing format:
#### @<author>- commit/PR link (or commit SHA if no link is available)
- list only files for which rebasing rules were added/updated
- separator
---
- Append a new entry in existing format:
-
Validate before finishing
- Determine the upstream ref from
rebase.shand use that exact ref for validation (do not hardcode a release branch in the skill output).- Example source of truth in
rebase.sh:UPSTREAM_VERSION=$(git rev-parse upstream-code/release/1.108) - If the script later points to
upstream-code/mainor another release branch, use that new ref instead.
- Example source of truth in
bash -n rebase.sh- JSON validation for changed
.rebase/**/*.jsonfiles (jq empty <file>) - For each changed
.rebase/replace/**/*.json, verify everyfromexists in the upstream file content before finishing.- Example:
git show <upstream-ref>:<path-without-code-prefix>and compare with thefromsnippet. path-without-code-prefixmeans the same file path but without the leadingcode/(becauseupstream-codestores VS Code sources at repo root).
- Example:
- Verify each
fromappears exactly once in the upstream file. If it matches multiple times, the rule will silently replace all of them. Extend thefromsnippet with more context until it is unique. - Dry-run the generated rule using the same replacement path as
rebase.sh(Perl-based multiline replace), not a language-native.replace(...). - Include at least one test case where
from/bycontains$(for example template literals like${key}) and confirm replacement still succeeds. - Re-check exclusions:
- no rules for
code/extensions/che-* - no rules for
package-lock.json
- no rules for
- Ensure every changed rule file is actually referenced by logic in
rebase.shwhen required.
- Determine the upstream ref from
-
Verify completeness — no uncovered Che-specific changes
- For each file that was updated or created in
.rebase/replace/, simulate the full rule application:- Start with the upstream file at
CURRENT_UPSTREAM_VERSION. - Apply all rule entries from the JSON (not just the newly added ones) plus any custom inline replacements from
rebase.sh. - Diff the result against the che-code working tree file.
- Start with the upstream file at
- If the diff is empty → all Che changes are covered. Good.
- If there is a remaining diff → there are Che-specific changes in the working tree that are not covered by any rule. These changes would be silently lost during rebase.
- If the uncovered changes are from the same commit being processed, add additional rule entries for them.
- If the uncovered changes are pre-existing (from earlier commits), report them to the user as a warning: "Pre-existing Che-specific changes at lines X-Y have no rebase rule and would be lost during rebase."
- For each file that was updated or created in
Decision notes
- Goal is to protect Che-specific behavior during upstream subtree rebases while keeping deltas in upstream files minimal.
- Prefer moving larger Che logic into Che-owned files and keeping upstream file edits small; then create replace rules only for the upstream file edits.
- When unsure between
addvsoverridefor JSON, follow existing.rebaseconventions in neighboring files and keep the smallest rule payload that reproduces the required result.
Examples
-
Dependency override updates across many
code/**/package.jsonfiles:- Example commit:
04b7984047fec31dd6993bd299f6698750c63d08 - Matching rule-update style:
eec9cd1e9e199ce9a0eb2f6e3bd1dad6fc258413
- Example commit:
-
Source-level VS Code file changes protected by replace rules:
- Example PR changes:
https://github.com/che-incubator/che-code/pull/617/changes - Matching rule commit:
https://github.com/che-incubator/che-code/pull/617/changes/e794c63f01d116b0b92d5ecd220247e13a5ba946
- Example PR changes:
Signals
- GitHub stars
- 35
- Forks
- 50
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
add-rebase-rules- Source
- github.com/che-incubator/che-code