Project 10: Stacked PRs Manager — Handle Dependent Pull Requests
A tool for managing stacked (dependent) pull requests—where PR 2 depends on PR 1, PR 3 depends on PR 2, etc. The tool handles rebasing the stack when upstream changes, updating PR descriptions with dependency info, and orchestrating merges in order.
Quick Reference
| Attribute | Value |
|---|---|
| Difficulty | Advanced |
| Time Estimate | 2-3 weeks |
| Main Programming Language | Go |
| Alternative Programming Languages | Python, Rust, TypeScript |
| Coolness Level | Level 4: Hardcore Tech Flex |
| Business Potential | 3. The “Service & Support” Model |
| Prerequisites | Projects 1-7 completed, strong rebase understanding |
| Key Topics | Branch Dependencies, Cascading Rebase, PR Base Branches |
1. Learning Objectives
By completing this project, you will:
- Implement a working version of: A tool for managing stacked (dependent) pull requests—where PR 2 depends on PR 1, PR 3 depends on PR 2, etc. The tool handles rebasing the stack when upstream changes, updating PR descriptions with dependency info, and orchestrating merges in order..
- Explain the core Git workflow tradeoff this project is designed to surface.
- Design deterministic checks so results can be verified and reproduced.
- Document operational failure modes and safe recovery actions.
2. All Theory Needed (Per-Concept Breakdown)
Branch Dependencies
Fundamentals
This concept matters in this project because your implementation will fail or become non-deterministic without a precise model of Branch Dependencies. You should define what the concept controls, what invariants must hold, and which actions are safe versus destructive. Treat this concept as a production concern, not a tutorial checkbox.
Deep Dive into the concept
When applying Branch Dependencies in this project, reason in three passes: data shape, state transitions, and enforcement. First, identify which artifacts are authoritative (commit objects, refs, metadata, policy config, CI status, or scan findings). Second, map how those artifacts change when your tool runs. Third, define failure behavior explicitly. In Git tooling, silent partial success is dangerous: you need either complete success with evidence or an explicit failure state with remediation guidance. Also account for scale behavior. A workflow that works on a toy repo may fail on large history depth, concurrent updates, or mixed branch policies. Include trace logs for every irreversible action, and separate simulation mode from write mode. For interview readiness, be able to explain how this concept protects delivery speed while reducing operational risk.
How this fit on projects
In this project, Branch Dependencies is directly used in design decisions, implementation constraints, and verification criteria.
Definitions & key terms
Branch Dependenciesinvariant: A condition that must remain true before and after every operation.- Safety boundary: The point where actions become destructive unless guarded.
- Verification signal: Evidence proving the action behaved as expected.
Mental model diagram
Input state -> Validate invariant -> Apply change -> Verify output -> Record evidence
How it works
- Capture current state and constraints.
- Evaluate whether
Branch Dependenciespreconditions are satisfied. - Execute the minimal safe transition.
- Verify postconditions and publish an auditable result.
Failure modes: stale state, partial writes, race conditions, ambiguous output contracts.
Minimal concrete example
Plan -> dry-run -> execute -> verify -> rollback/forward-fix decision
Common misconceptions
- Assuming local success implies team-safe behavior.
- Treating policy violations as warnings instead of merge blockers.
- Skipping deterministic verification because the output appears correct.
Check-your-understanding questions
- Which invariant is most likely to break first under concurrency?
- What output proves your tool handled an edge case correctly?
- Where should enforcement happen: local hook, CI, or protected branch gate?
Check-your-understanding answers
- The invariant tied to mutable refs or policy-dependent merge eligibility.
- A deterministic transcript showing both success and controlled failure behavior.
- Layered enforcement: fast local checks plus non-bypassable server-side gates.
Real-world applications
- Change-management tooling for fast-moving teams.
- Incident-safe release workflows with traceable rollback paths.
- Compliance-ready source-control automation.
Where you’ll apply it This project and its immediate adjacent projects in this sprint.
References
- https://git-scm.com/docs
- https://dora.dev/capabilities/trunk-based-development/
Key insights
Branch Dependencies is only valuable when its invariants are encoded into tooling and checks.
Summary
Mastering Branch Dependencies here gives you transferable patterns for larger workflow systems.
Homework/Exercises to practice the concept
- Write one failing scenario and expected detection output.
- Define one invariant and one explicit violation test.
Solutions to the homework/exercises
- Use a stale branch or invalid metadata case and assert deterministic error reporting.
- Invariant: protected branch must not accept unchecked changes; violation test: bypass attempt should fail fast.
Cascading Rebase
Fundamentals
This concept matters in this project because your implementation will fail or become non-deterministic without a precise model of Cascading Rebase. You should define what the concept controls, what invariants must hold, and which actions are safe versus destructive. Treat this concept as a production concern, not a tutorial checkbox.
Deep Dive into the concept
When applying Cascading Rebase in this project, reason in three passes: data shape, state transitions, and enforcement. First, identify which artifacts are authoritative (commit objects, refs, metadata, policy config, CI status, or scan findings). Second, map how those artifacts change when your tool runs. Third, define failure behavior explicitly. In Git tooling, silent partial success is dangerous: you need either complete success with evidence or an explicit failure state with remediation guidance. Also account for scale behavior. A workflow that works on a toy repo may fail on large history depth, concurrent updates, or mixed branch policies. Include trace logs for every irreversible action, and separate simulation mode from write mode. For interview readiness, be able to explain how this concept protects delivery speed while reducing operational risk.
How this fit on projects
In this project, Cascading Rebase is directly used in design decisions, implementation constraints, and verification criteria.
Definitions & key terms
Cascading Rebaseinvariant: A condition that must remain true before and after every operation.- Safety boundary: The point where actions become destructive unless guarded.
- Verification signal: Evidence proving the action behaved as expected.
Mental model diagram
Input state -> Validate invariant -> Apply change -> Verify output -> Record evidence
How it works
- Capture current state and constraints.
- Evaluate whether
Cascading Rebasepreconditions are satisfied. - Execute the minimal safe transition.
- Verify postconditions and publish an auditable result.
Failure modes: stale state, partial writes, race conditions, ambiguous output contracts.
Minimal concrete example
Plan -> dry-run -> execute -> verify -> rollback/forward-fix decision
Common misconceptions
- Assuming local success implies team-safe behavior.
- Treating policy violations as warnings instead of merge blockers.
- Skipping deterministic verification because the output appears correct.
Check-your-understanding questions
- Which invariant is most likely to break first under concurrency?
- What output proves your tool handled an edge case correctly?
- Where should enforcement happen: local hook, CI, or protected branch gate?
Check-your-understanding answers
- The invariant tied to mutable refs or policy-dependent merge eligibility.
- A deterministic transcript showing both success and controlled failure behavior.
- Layered enforcement: fast local checks plus non-bypassable server-side gates.
Real-world applications
- Change-management tooling for fast-moving teams.
- Incident-safe release workflows with traceable rollback paths.
- Compliance-ready source-control automation.
Where you’ll apply it This project and its immediate adjacent projects in this sprint.
References
- https://git-scm.com/docs
- https://dora.dev/capabilities/trunk-based-development/
Key insights
Cascading Rebase is only valuable when its invariants are encoded into tooling and checks.
Summary
Mastering Cascading Rebase here gives you transferable patterns for larger workflow systems.
Homework/Exercises to practice the concept
- Write one failing scenario and expected detection output.
- Define one invariant and one explicit violation test.
Solutions to the homework/exercises
- Use a stale branch or invalid metadata case and assert deterministic error reporting.
- Invariant: protected branch must not accept unchecked changes; violation test: bypass attempt should fail fast.
PR Base Branches
Fundamentals
This concept matters in this project because your implementation will fail or become non-deterministic without a precise model of PR Base Branches. You should define what the concept controls, what invariants must hold, and which actions are safe versus destructive. Treat this concept as a production concern, not a tutorial checkbox.
Deep Dive into the concept
When applying PR Base Branches in this project, reason in three passes: data shape, state transitions, and enforcement. First, identify which artifacts are authoritative (commit objects, refs, metadata, policy config, CI status, or scan findings). Second, map how those artifacts change when your tool runs. Third, define failure behavior explicitly. In Git tooling, silent partial success is dangerous: you need either complete success with evidence or an explicit failure state with remediation guidance. Also account for scale behavior. A workflow that works on a toy repo may fail on large history depth, concurrent updates, or mixed branch policies. Include trace logs for every irreversible action, and separate simulation mode from write mode. For interview readiness, be able to explain how this concept protects delivery speed while reducing operational risk.
How this fit on projects
In this project, PR Base Branches is directly used in design decisions, implementation constraints, and verification criteria.
Definitions & key terms
PR Base Branchesinvariant: A condition that must remain true before and after every operation.- Safety boundary: The point where actions become destructive unless guarded.
- Verification signal: Evidence proving the action behaved as expected.
Mental model diagram
Input state -> Validate invariant -> Apply change -> Verify output -> Record evidence
How it works
- Capture current state and constraints.
- Evaluate whether
PR Base Branchespreconditions are satisfied. - Execute the minimal safe transition.
- Verify postconditions and publish an auditable result.
Failure modes: stale state, partial writes, race conditions, ambiguous output contracts.
Minimal concrete example
Plan -> dry-run -> execute -> verify -> rollback/forward-fix decision
Common misconceptions
- Assuming local success implies team-safe behavior.
- Treating policy violations as warnings instead of merge blockers.
- Skipping deterministic verification because the output appears correct.
Check-your-understanding questions
- Which invariant is most likely to break first under concurrency?
- What output proves your tool handled an edge case correctly?
- Where should enforcement happen: local hook, CI, or protected branch gate?
Check-your-understanding answers
- The invariant tied to mutable refs or policy-dependent merge eligibility.
- A deterministic transcript showing both success and controlled failure behavior.
- Layered enforcement: fast local checks plus non-bypassable server-side gates.
Real-world applications
- Change-management tooling for fast-moving teams.
- Incident-safe release workflows with traceable rollback paths.
- Compliance-ready source-control automation.
Where you’ll apply it This project and its immediate adjacent projects in this sprint.
References
- https://git-scm.com/docs
- https://dora.dev/capabilities/trunk-based-development/
Key insights
PR Base Branches is only valuable when its invariants are encoded into tooling and checks.
Summary
Mastering PR Base Branches here gives you transferable patterns for larger workflow systems.
Homework/Exercises to practice the concept
- Write one failing scenario and expected detection output.
- Define one invariant and one explicit violation test.
Solutions to the homework/exercises
- Use a stale branch or invalid metadata case and assert deterministic error reporting.
- Invariant: protected branch must not accept unchecked changes; violation test: bypass attempt should fail fast.
3. Project Specification
3.1 What You Will Build
A tool for managing stacked (dependent) pull requests—where PR 2 depends on PR 1, PR 3 depends on PR 2, etc. The tool handles rebasing the stack when upstream changes, updating PR descriptions with dependency info, and orchestrating merges in order.
3.2 Functional Requirements
- Scope control: Deliver a deterministic and testable implementation.
- Correctness: Preserve Git invariants and policy constraints.
3.3 Non-Functional Requirements
- Performance: Deterministic execution with documented runtime behavior on representative history sizes.
- Reliability: Repeated runs on the same input produce identical outputs.
- Usability: Clear CLI or report output for both success and failure cases.
3.4 Example Usage / Output
You’ll have a CLI for managing PR stacks:
Example Output:
$ stack create auth-refactor
Created stack 'auth-refactor' based on main
$ stack branch add-user-model
Created branch 'auth-refactor/add-user-model' in stack
# ... make commits...
$ stack branch add-login-endpoint
Created branch 'auth-refactor/add-login-endpoint' on top of 'add-user-model'
# ... make commits...
$ stack branch add-login-ui
Created branch 'auth-refactor/add-login-ui' on top of 'add-login-endpoint'
# ... make commits...
$ stack status
Stack: auth-refactor (based on main)
main
└── add-user-model (3 commits, PR #127)
└── add-login-endpoint (5 commits, PR #128)
└── add-login-ui (4 commits, PR #129) ← HEAD
All branches up to date with their bases.
$ stack push
Pushing stack to origin...
✓ Pushed auth-refactor/add-user-model
✓ Pushed auth-refactor/add-login-endpoint
✓ Pushed auth-refactor/add-login-ui
Creating/updating PRs...
✓ PR #127: Add user model
Base: main
Description updated with stack info
✓ PR #128: Add login endpoint
Base: auth-refactor/add-user-model
Description updated with stack info:
"⬆️ Depends on: #127 (Add user model)
⬇️ Blocks: #129 (Add login UI)"
✓ PR #129: Add login UI
Base: auth-refactor/add-login-endpoint
Description updated with stack info:
"⬆️ Depends on: #128 (Add login endpoint)"
$ # Someone merges PR #127...
$ stack sync
Syncing stack with origin...
Fetching updates...
PR #127 was merged to main!
Rebasing stack...
Rebasing add-login-endpoint onto main...
✓ Rebased successfully (was based on add-user-model)
Rebasing add-login-ui onto add-login-endpoint...
✓ Rebased successfully
Updating PRs...
✓ PR #128: Base changed to main (was add-user-model)
✓ PR #129: No changes needed
Stack synced! Ready for more merges.
3.5 Data Formats / Schemas / Protocols
Describe input repository assumptions, output report shape, and any policy/config schema consumed by the tool.
3.6 Edge Cases
- Empty repository or shallow clone state.
- Detached HEAD or rewritten history during execution.
- Invalid metadata/policy configuration.
3.7 Real World Outcome
You’ll have a CLI for managing PR stacks:
Example Output:
$ stack create auth-refactor
Created stack 'auth-refactor' based on main
$ stack branch add-user-model
Created branch 'auth-refactor/add-user-model' in stack
# ... make commits...
$ stack branch add-login-endpoint
Created branch 'auth-refactor/add-login-endpoint' on top of 'add-user-model'
# ... make commits...
$ stack branch add-login-ui
Created branch 'auth-refactor/add-login-ui' on top of 'add-login-endpoint'
# ... make commits...
$ stack status
Stack: auth-refactor (based on main)
main
└── add-user-model (3 commits, PR #127)
└── add-login-endpoint (5 commits, PR #128)
└── add-login-ui (4 commits, PR #129) ← HEAD
All branches up to date with their bases.
$ stack push
Pushing stack to origin...
✓ Pushed auth-refactor/add-user-model
✓ Pushed auth-refactor/add-login-endpoint
✓ Pushed auth-refactor/add-login-ui
Creating/updating PRs...
✓ PR #127: Add user model
Base: main
Description updated with stack info
✓ PR #128: Add login endpoint
Base: auth-refactor/add-user-model
Description updated with stack info:
"⬆️ Depends on: #127 (Add user model)
⬇️ Blocks: #129 (Add login UI)"
✓ PR #129: Add login UI
Base: auth-refactor/add-login-endpoint
Description updated with stack info:
"⬆️ Depends on: #128 (Add login endpoint)"
$ # Someone merges PR #127...
$ stack sync
Syncing stack with origin...
Fetching updates...
PR #127 was merged to main!
Rebasing stack...
Rebasing add-login-endpoint onto main...
✓ Rebased successfully (was based on add-user-model)
Rebasing add-login-ui onto add-login-endpoint...
✓ Rebased successfully
Updating PRs...
✓ PR #128: Base changed to main (was add-user-model)
✓ PR #129: No changes needed
Stack synced! Ready for more merges.
4. Solution Architecture
4.1 High-Level Design
Inputs -> Validation -> Core Engine -> Output Formatter -> Verification Report
4.2 Key Components
| Component | Responsibility | Key Decisions |
|---|---|---|
| Input loader | Discover commits/refs/config inputs | Deterministic ordering and clear failure messages |
| Core engine | Compute project-specific logic | Separate read-only simulation from mutating actions |
| Reporter | Produce user-facing output and evidence | Include machine-readable and human-readable forms |
4.4 Data Structures (No Full Code)
ProjectState { refs, commits, policy, findings, metrics }
Result { status, evidence, warnings, next_actions }
4.4 Algorithm Overview
- Collect state from repository and configuration.
- Evaluate invariants and policy preconditions.
- Execute core transformation or analysis logic.
- Verify postconditions and emit deterministic report.
Complexity Analysis:
- Time: O(history + affected scope)
- Space: O(active graph window + report size)
5. Implementation Guide
5.1 Development Environment Setup
Use the environment defined in the main guide. Pin tool versions and fixture data to keep outputs reproducible.
5.2 Project Structure
project-root/
├── fixtures/
├── src/
├── tests/
├── docs/
└── README.md
5.3 The Core Question You’re Answering
“How do you break large features into reviewable chunks while keeping them synchronized?”
Before you write any code, sit with this question. Large PRs are hard to review, but splitting a feature into dependent PRs creates a maintenance burden. The solution is tooling that automates the cascade.
5.4 Concepts You Must Understand First
Stop and research these before coding:
- Branch Dependencies
- How do you model “branch B is based on branch A”?
- What happens to B when A gets new commits?
- What happens when A is rebased or merged?
- Book Reference: “Pro Git” Ch. 3.6 — Chacon
- Cascading Rebase
- How do you rebase a chain of branches?
- What order should you rebase in?
- How do you handle conflicts in the middle of a chain?
- Book Reference: “Pro Git” Ch. 7.6 — Chacon
- PR Base Branches
- How do you set a PR’s base branch to another branch (not main)?
- What happens to a PR when its base branch is merged?
- How do you update a PR’s base branch via API?
- Resource: GitHub REST API documentation
5.5 Questions to Guide Your Design
Before implementing, think through these:
- Stack Representation
- How will you store the stack metadata (which branch is on top of which)?
- Should this be in .git, a config file, or derived from branch names?
- How do you handle branches that are part of multiple stacks?
- Sync Algorithm
- When main changes, how do you detect which stacks need updating?
- When a PR is merged, how do you update the stack?
- What if a rebase has conflicts?
- PR Management
- How do you set up a PR with a non-main base branch?
- How do you generate the “depends on/blocks” description?
- How do you keep PR descriptions in sync with stack state?
5.6 Thinking Exercise
Trace a Stack Update
Simulate a stack update on paper:
Initial state:
main ← A ← B (add-user-model)
└← C ← D (add-login-endpoint)
└← E ← F (add-login-ui)
Action: Main gets new commit X
main ← X
Desired state:
main ← X ← A' ← B' (add-user-model)
└← C' ← D' (add-login-endpoint)
└← E' ← F' (add-login-ui)
Questions while tracing:
- In what order do you rebase the branches?
- What commands do you run for each rebase?
- Why are A’, B’, C’, etc. different commits (different SHAs)?
- What if commit C conflicts with commit X?
5.7 The Interview Questions They’ll Ask
Prepare to answer these:
- “How would you design a system for managing dependent pull requests?”
- “What happens when a branch in the middle of a stack gets merged?”
- “How do you handle rebase conflicts in a stack of branches?”
- “What are the tradeoffs between stacked PRs and a single large PR?”
- “How would you implement ‘stacking’ without special tooling?”
5.8 Hints in Layers
Hint 1: Starting Point
Store stack metadata in .git/stack-info/. For each stack, record the ordered list of branches.
Hint 2: Rebase Order Always rebase from bottom of stack to top. If you rebase the top first, you’ll have to redo it when you rebase its base.
Hint 3: Detecting Merges Check if a branch’s base exists on the remote. If the base is merged into main, main becomes the new base.
Hint 4: PR Updates
Use gh api or PyGithub to update PR base branches. When base is merged, GitHub automatically retargets to main.
5.9 Books That Will Help
| Topic | Book | Chapter |
|---|---|---|
| Rebase mechanics | “Pro Git” by Chacon | Ch. 3.6, 7.6 |
| Branch workflows | “Pro Git” by Chacon | Ch. 5.1-5.3 |
| GitHub CLI | gh documentation | — |
5.10 Implementation Phases
Phase 1: Foundation (1-2 sessions)
- Define fixtures, expected outputs, and invariant checks.
- Build read-only analysis path.
Phase 2: Core Functionality (2-4 sessions)
- Implement project-specific core logic and deterministic reporting.
- Add policy and edge-case handling.
Phase 3: Polish and Edge Cases (1-2 sessions)
- Add failure demos, performance notes, and usability improvements.
- Finalize docs and validation transcripts.
5.11 Key Implementation Decisions
| Decision | Options | Recommendation | Rationale |
|---|---|---|---|
| Execution mode | direct write vs dry-run+write | dry-run+write | Safer and easier to debug |
| Output contract | free text vs structured+text | structured+text | Better automation and readability |
| Enforcement location | local only vs local+CI | local+CI | Prevents bypass in shared branches |
6. Testing Strategy
6.1 Test Categories
- Unit tests for parsing and policy logic.
- Integration tests on fixture repositories.
- Edge-case tests for stale refs, malformed metadata, and large histories.
6.2 Critical Test Cases
- Deterministic golden-path scenario.
- Policy violation hard-fail scenario.
- Recovery path after partial or conflicting state.
6.3 Test Data
Use fixed repository fixtures with known commit graphs and expected outputs stored under version control.
7. Common Pitfalls & Debugging
Problem 1: “Output looks correct but history or metadata is inconsistent”
- Why: Validation happens after mutation, not before.
- Fix: Add a preflight invariant check and a post-write verification step.
- Quick test: Run the same command twice on the same fixture and verify identical results.
Problem 2: “Tool works on small repo but times out on larger history”
- Why: Full traversal is performed where selective traversal is possible.
- Fix: Cache intermediate graph lookups and scope analysis to affected commits/paths.
- Quick test: Compare runtime on small and large fixtures with a clear budget target.
Problem 3: “Policy check can be bypassed by local-only behavior”
- Why: Enforcement is advisory, not server-authoritative.
- Fix: Mirror critical checks in CI and protected branch rules.
- Quick test: Attempt merge with failing policy in CI and confirm hard block.
8. Extensions & Challenges
8.1 Beginner Extensions
- Add richer error messages with remediation hints.
- Add fixture generation helpers for repeatable demos.
8.2 Intermediate Extensions
- Add performance instrumentation and budget assertions.
- Add policy configuration profiles by repository type.
8.3 Advanced Extensions
- Add distributed execution support for large repositories.
- Add signed evidence exports for compliance workflows.
9. Real-World Connections
9.1 Industry Applications
- Internal developer portals.
- Enterprise repository governance systems.
- Release safety and incident diagnostics tooling.
9.2 Related Open Source Projects
- Git core: https://git-scm.com/
- GitHub CLI: https://github.com/cli/cli
- pre-commit framework: https://pre-commit.com/
9.3 Interview Relevance
This project prepares you for architecture and debugging interviews that focus on merge policy, CI gates, and workflow reliability tradeoffs.
10. Resources
10.1 Essential Reading
- Pro Git (Internals and Workflows chapters)
- Software Engineering at Google (Version control and build chapters)
- Accelerate (delivery performance practices)
10.2 Video Resources
- Git internals talks from Git Merge conference archives.
- DORA and delivery metrics conference sessions.
10.3 Tools and Documentation
- https://git-scm.com/docs
- https://docs.github.com/
- https://dora.dev/
10.4 Related Projects in This Series
- Previous: 9: “Git Bisect Automator — Debug Regressions with Binary Search
- Next: 11: “Conventional Commits Enforcer — Automate Semantic Versioning
11. Self-Assessment Checklist
11.1 Understanding
- I can explain the primary invariant this project enforces.
- I can explain one failure mode and one safe recovery path.
11.2 Implementation
- Functional requirements are met on deterministic fixtures.
- Critical edge cases are tested and documented.
11.3 Growth
- I can describe tradeoffs in an interview setting.
- I documented what I would change in a production version.
12. Submission / Completion Criteria
Minimum Viable Completion:
- Deterministic golden-path output exists.
- One failure scenario is handled with clear output.
- Core workflow objective is demonstrably met.
Full Completion:
- Minimum criteria plus policy validation, structured reporting, and edge-case coverage.
Excellence:
- Full completion plus measurable performance budget and production-hardening notes.