mit einem Klick
rebase-branch-on-master
// Safely rebases the current feature branch onto a target branch (default: main) with automatic stash handling and conflict detection.
// Safely rebases the current feature branch onto a target branch (default: main) with automatic stash handling and conflict detection.
Adds a GitMCP URL for a GitHub repository to the project's MCP configuration (.cursor/mcp.json).
Manage GitHub issues - create, edit, close, comment, assign, and delegate to Copilot. Uses GitHub MCP.
Squashes multiple commits on the current branch into a single commit with an auto-generated message, then pushes.
| name | rebase-branch-on-master |
| description | Safely rebases the current feature branch onto a target branch (default: main) with automatic stash handling and conflict detection. |
You are a Git workflow assistant that safely rebases the current branch onto a target branch.
| Parameter | Required | Default | Description |
|---|---|---|---|
target_branch | No | main | The branch to rebase onto. User can specify any branch name. |
Example invocations:
maindevelopfeature/baseBefore doing anything, verify ALL of the following. If ANY check fails, STOP and report the issue (and restore stash if already created):
origin remote must be configuredgit ls-remote).git/rebase-merge, .git/MERGE_HEAD, .git/CHERRY_PICK_HEADIf a stash was created, it MUST be restored before reporting any error.
This is non-negotiable. Use try-finally logic:
# Save current branch name
CURRENT_BRANCH=$(git branch --show-current)
# Target branch: use user-specified or default to "main"
TARGET_BRANCH="${USER_SPECIFIED_TARGET:-main}"
# Verify target branch exists (locally or on remote)
if ! git show-ref --verify --quiet "refs/heads/$TARGET_BRANCH" && \
! git show-ref --verify --quiet "refs/remotes/origin/$TARGET_BRANCH"; then
echo "ERROR: Target branch '$TARGET_BRANCH' does not exist locally or on remote"
exit 1
fi
# Verify we're not already on the target branch
if [ "$CURRENT_BRANCH" = "$TARGET_BRANCH" ]; then
echo "ERROR: Already on target branch '$TARGET_BRANCH'. Cannot rebase onto itself."
exit 1
fi
Check for uncommitted changes and stash them:
# Check for any changes
HAS_CHANGES=false
if ! git diff --cached --quiet || ! git diff --quiet || [ -n "$(git ls-files --others --exclude-standard)" ]; then
HAS_CHANGES=true
fi
STASH_CREATED=false
STASH_MSG=""
if [ "$HAS_CHANGES" = true ]; then
# Stash everything including untracked files, with a unique marker
STASH_MSG="rebase-skill-auto-stash-$(date +%s)-$$"
git stash push -u -m "$STASH_MSG"
STASH_CREATED=true
echo "Stash created: $STASH_MSG"
fi
From this point on, ANY error must restore the stash first!
# Fetch latest from remote
git fetch origin
# If target branch exists locally, update it
if git show-ref --verify --quiet "refs/heads/$TARGET_BRANCH"; then
git checkout "$TARGET_BRANCH"
if ! git pull origin "$TARGET_BRANCH" --ff-only; then
echo "ERROR: Cannot fast-forward $TARGET_BRANCH. Local branch has diverged."
# RESTORE STASH BEFORE EXITING
restore_stash_if_needed
exit 1
fi
fi
# Return to the original branch
git checkout "$CURRENT_BRANCH"
# Attempt rebase onto target (use origin/target if local doesn't exist)
if git show-ref --verify --quiet "refs/heads/$TARGET_BRANCH"; then
REBASE_TARGET="$TARGET_BRANCH"
else
REBASE_TARGET="origin/$TARGET_BRANCH"
fi
if ! git rebase "$REBASE_TARGET"; then
# Rebase failed - ABORT to preserve original state
git rebase --abort
echo "ERROR: Rebase failed due to conflicts. Aborted to preserve original state."
# RESTORE STASH BEFORE EXITING
restore_stash_if_needed
exit 1
fi
echo "Rebase successful!"
Only if rebase succeeded:
# Use --force-with-lease for safety (fails if remote has new commits we don't know about)
if ! git push --force-with-lease origin "$CURRENT_BRANCH"; then
echo "WARNING: Push failed. Someone else may have pushed to this branch."
echo "Local rebase is intact. You can retry push manually or investigate."
# Still restore stash - this is a warning, not a fatal error
fi
This step MUST run regardless of success/failure (if stash was created):
restore_stash_if_needed() {
if [ "$STASH_CREATED" = true ] && [ -n "$STASH_MSG" ]; then
# Find our stash by its unique message
STASH_REF=$(git stash list | grep "$STASH_MSG" | head -1 | cut -d: -f1)
if [ -n "$STASH_REF" ]; then
# Use --index to PRESERVE the staged/unstaged structure
if git stash pop --index "$STASH_REF"; then
echo "Stash restored successfully (staged/unstaged structure preserved)"
else
# If --index fails (can happen with conflicts), try without it
echo "WARNING: Could not restore with staged/unstaged structure."
echo "Attempting plain restore..."
git stash pop "$STASH_REF" || {
echo "ERROR: Stash restore failed. Your changes are still in stash: $STASH_REF"
echo "Run 'git stash list' to see it and 'git stash pop' to restore manually."
}
fi
else
echo "WARNING: Could not find stash with message: $STASH_MSG"
fi
fi
}
# Always call this at the end
restore_stash_if_needed
| Scenario | Action |
|---|---|
| Target branch doesn't exist | STOP immediately (before stash) |
| Already on target branch | STOP immediately (before stash) |
| Detached HEAD | STOP immediately (before stash) |
| Ongoing rebase/merge | STOP immediately (before stash) |
| Network unreachable | Restore stash, then STOP |
| Target branch diverged | Restore stash, then STOP |
| Rebase conflicts | Abort rebase, restore stash, then STOP |
| Push rejected | Restore stash, report warning (keep local rebase) |
| Stash pop conflicts | Report โ changes remain in stash for manual recovery |
Report the following at each stage:
{branch_name}{target_branch} (user-specified or default){yes|no}{success|failure}{success|aborted due to conflicts}{success|failed|skipped}{yes (with index)|yes (without index)|failed|N/A}git stash pop --index to maintain staging structure--force-with-lease which fails if remote has unexpected commits