batch-pr-rebase
Included with Lifetime
$97 forever
Batch rebase multiple PRs against main to resolve conflicts and fix CI failures
ci-cdgitrebasepr-managementconflict-resolutionci-fixesworktree
What this skill does
# Batch PR Rebase
## Overview
| Field | Value |
| --- | --- |
| **Date** | 2026-02-08 |
| **Objective** | Rebase 5 open PRs against main to resolve `.gitleaks.toml` conflicts and fix `secret-scan` CI failures |
| **Outcome** | ✅ Success - 5/5 PRs rebased, all conflicts resolved, all mergeable |
| **Context** | PR #3119 merged gitleaks fix to main; 3 PRs had conflicts; all 5 had outdated workflows |
## When to Use This Skill
Use this workflow when:
- ✅ Multiple open PRs need rebasing against updated main branch
- ✅ PRs have merge conflicts from the same file (e.g., config file updated on main)
- ✅ PRs have CI failures due to outdated workflow files
- ✅ You need to clean up commit history (remove redundant "retrigger CI" commits)
- ✅ Some PRs are in worktrees, others are not
**Don't use when**:
- ❌ Only 1-2 PRs need rebasing (use standard `git rebase` workflow)
- ❌ PRs have complex multi-file conflicts requiring manual resolution
- ❌ PRs are from external contributors (coordinate with them first)
## Verified Workflow
### Step 1: Prepare - Fetch and Update Main
```bash
# Fetch latest from remote
git fetch origin
# Update local main branch
git checkout main && git pull origin main
```
**Why this works**: Ensures your local main has the latest changes before rebasing PRs.
### Step 2: Identify Meaningful Commits
For each PR, identify which commits contain actual work vs. CI fixes:
```bash
# View commits unique to PR branch
git log --oneline origin/main..<branch-name>
# Example output:
# 391a2912 chore: retrigger CI ❌ Drop this
# d38c6663 fix(ci): add .gitleaks.toml ❌ Drop this (superseded by main)
# bdbb3d71 fix(data): replace Optional ✅ Keep this (meaningful work)
```
**Pattern**: Drop commits that:
- Are labeled "chore: retrigger CI"
- Add files that main already has (like `.gitleaks.toml`)
- Only exist to fix CI on the old branch
### Step 3: Rebase Using Cherry-Pick (Cleanest Method)
For PRs with conflicts, use the cherry-pick approach:
```bash
# Find the meaningful commit hash
git log --oneline --all | grep "<search-term>"
# Example: git log --oneline --all | grep "fix(data): replace Optional"
# Recreate branch from main
git checkout main
git checkout -B <branch-name> origin/main
# Cherry-pick only the meaningful commit
git cherry-pick <commit-hash>
# Verify only meaningful commit remains
git log --oneline origin/main..HEAD
# Force push (safe because we recreated from main)
git push --force-with-lease origin <branch-name>
```
**Why this works**:
- Creates clean history without conflict markers
- Automatically drops superseded commits
- Safer than interactive rebase for complex conflicts
### Step 4: Handle Worktrees
If a PR branch exists in a worktree:
```bash
# Check for worktree error
git checkout <branch-name>
# Error: 'branch-name' is already used by worktree at '/path/to/worktree'
# Work in the worktree instead
cd /path/to/worktree
# Remove untracked conflict files
rm .gitleaks.toml # Or any other untracked files causing conflicts
# Rebase normally
git rebase origin/main
# Push from worktree
git push --force-with-lease origin <branch-name>
```
**Why this works**: Git prevents checking out a branch in multiple locations; worktrees require in-place operations.
### Step 5: Verify Results
After rebasing all PRs:
```bash
# Check PR status
for pr in 3118 3117 3116 3115 3114; do
echo "=== PR #$pr ==="
gh pr view $pr --json number,title,mergeable,statusCheckRollup \
--jq '{number, title, mergeable, failing_checks: [.statusCheckRollup[] | select(.conclusion == "FAILURE") | .name]}'
echo ""
done
```
**Success criteria**:
- `mergeable: "MERGEABLE"` for all PRs
- `secret-scan` and `security-report` failures resolved
- Commit history clean (only meaningful commits)
## Failed Attempts & Lessons Learned
### ❌ Failed: Interactive Rebase Kept Wrong Commits
**What I tried**:
```bash
git rebase -i origin/main
# In editor: kept all 3 commits, then manually skipped conflict
```
**What happened**: After skipping the `.gitleaks.toml` conflict, the "chore: retrigger CI" commit remained.
**Why it failed**: Interactive rebase applies commits sequentially; skipping one doesn't skip dependent commits.
**What I learned**: For complex conflict scenarios, cherry-pick is cleaner than interactive rebase.
### ❌ Failed: Git Reset Hard Blocked by Safety Net
**What I tried**:
```bash
git reset --hard origin/main && git cherry-pick bdbb3d71
```
**What happened**: Safety Net hook blocked the command.
**Why it failed**: `git reset --hard` destroys uncommitted changes; hook correctly prevented it.
**What I learned**: Use `git checkout -B` instead of reset for recreating branches.
### ❌ Failed: Rebasing in Main Repo When Worktree Exists
**What I tried**:
```bash
git checkout skill/architecture/dtype-native-migration
# Error: already used by worktree at '/path/to/worktree'
```
**What happened**: Git prevents multiple checkouts of the same branch.
**Why it failed**: Worktrees lock branches to prevent conflicts.
**What I learned**: Always check for worktrees first; work in the worktree if it exists.
### ⚠️ Partial Success: Removing Untracked Conflict Files
**What I tried**:
```bash
cd /path/to/worktree
git rebase origin/main
# Error: untracked .gitleaks.toml would be overwritten
```
**Solution**:
```bash
rm .gitleaks.toml
git rebase origin/main # Now succeeds
```
**Why it worked**: The file was untracked (from a previous conflict resolution), not part of the branch.
**What I learned**: Always check for untracked files before rebasing in worktrees.
## Results & Parameters
### Final PR Status
| PR | Branch | Status | Commits Dropped | CI Fixed |
| --- | --- | --- | --- | --- |
| #3118 | `fix-flaky-data-samplers-optional-int` | ✅ All passing | 2 | secret-scan, security-report |
| #3117 | `skill/debugging/fixme-todo-cleanup-v2` | ⚠️ pre-commit fail | 2 | secret-scan, security-report |
| #3116 | `skill/architecture/dtype-native-migration` | ⚠️ flaky test | 0 | secret-scan, security-report |
| #3115 | `feature/improve-import-tests-3033` | ✅ All passing | 2 | secret-scan, security-report |
| #3114 | `dependabot/github_actions/...` | ✅ All passing | 0 | secret-scan, security-report |
### Key Metrics
- **Total PRs rebased**: 5
- **Conflicts resolved**: 3 (all `.gitleaks.toml`)
- **Commits cleaned**: 6 (dropped redundant CI fixes)
- **CI failures fixed**: 10 (secret-scan + security-report on all 5 PRs)
- **Success rate**: 100% (all mergeable, conflicts resolved)
- **Time taken**: ~15 minutes for 5 PRs
### Commands Used
```bash
# 1. Preparation
git fetch origin
git checkout main && git pull origin main
# 2. Rebase with cherry-pick (for conflicting PRs)
git checkout main
git checkout -B <branch> origin/main
git cherry-pick <meaningful-commit-hash>
git push --force-with-lease origin <branch>
# 3. Rebase in worktree (for non-conflicting PRs)
cd /path/to/worktree
rm .gitleaks.toml # Remove untracked conflict files
git rebase origin/main
git push --force-with-lease origin <branch>
# 4. Verification
gh pr view <number> --json mergeable,statusCheckRollup
```
## Best Practices
1. **Always fetch first**: `git fetch origin` before starting
2. **Identify meaningful commits**: Use `git log --oneline origin/main..HEAD`
3. **Prefer cherry-pick for conflicts**: Cleaner than interactive rebase
4. **Check for worktrees**: Use worktree if branch already checked out there
5. **Remove untracked files**: `rm` any untracked conflict files before rebasing
6. **Force-push safely**: Use `--force-with-lease` instead of `--force`
7. **Verify immediately**: Check `gh pr view` after each rebase
## Related Skills
- `worktree-sync` - Syncing worktrees with main
- `gh-fix-pr-feedback` - Addressing PR review comments
- `fix-ci-failures` - Diagnosing and fixing CI issues
## References
- Session: 2026-02-08 batch PR rebase
- PRs: #3114-#3118
- Context: PR #3119 gitleaks fix merged to main