Stacked sessions and PRs bring order to a messy modernization
Modernizing an aging codebase is rarely a single, clean operation. It usually involves several related changes that depend on each other, and managing that flow can be as much of a challenge as writing the code itself. The GitHub Copilot app aims to smooth that out with stacked sessions and stacked pull requests, which let you build a chain of work where each step builds on the previous one.
To see how this plays out in practice, consider a personal project that had not been seriously updated since around 2016. The app depended on React 15, Less for CSS preprocessing, and a contemporaneous version of react-bootstrap. Attempts to modernize it had been abandoned before because the effort seemed disproportionate to the payoff.

That screenshot shows a set of stacked sessions—a series of tasks in the same repository where each session builds on the work of the one before it. In this case, that structure was the key to making progress without getting buried in a single enormous pull request.
Planning the first attempt
The first move was to try a one-shot modernization. A detailed prompt in Plan mode was passed to Claude Opus 4.8, with a Rubber Duck review from GPT-5.5. After several rounds of back-and-forth to settle decisions, the plan was approved and the app set to work. The attempt did not succeed, but the failure was instructive.
I want to modernize the frontend for this project. I first wrote a lot of this code more than 10 years ago and it should be cleaned up a lot. I'm thinking we start either using Tailwind or just vanilla CSS (please vet everything to help me decide), we remove all Less (etc), and clean everything up accessibility-wise and responsiveness-wise. Right now I really want to just focus on styles, and then slowly but surely organize and consolidate the React functionality. It might be worth modernizing dependencies, too. Let's come up with a plan around this before diving in.
1. Nothing is sacred, it's okay if we have to completely start over some parts
2. Links should change colors and add underlines on hover/focus
3. Input boxes should have a smaller border radius in general, and their labels should be cleaner
4. There should be good wrapping and a max-width on containers so that an input box doesn't span an entire wide monitor.
The problem was that the repo had an old dev branch with partially modernized code, and the new work was branching off main. The deployment in active use was built from the dev branch, so features developed there had to be included. The changes were just large enough that it made more sense to apply the new work to dev rather than pull the dev changes into main.

Copilot handled the pivot gracefully: it created a new session, closed the pull request that was no longer viable, and carried the styling decisions over to the changes being applied to the dev branch.
Testing surfaces a legacy dependency problem
With a solid branch and a decent pull request in place, testing revealed old warnings in the console—references to findDOMNode and componentWillReceiveProps. Those functions were not in the main codebase anymore, but they were coming from react-bootstrap. Plan mode was used again to figure out whether an upgrade would work or whether the library should be removed entirely.
Do you think we should remove react-bootstrap entirely (and replace with a modern alternative), or just upgrade/migrate existing components?
The plan recommended replacing the library outright, but that felt like significant scope creep for the current work. The temptation was to fold everything into one massive pull request, especially since the code was being generated rather than hand-written. The better move was to keep the work separated.
Stacking one session on another
Instead of expanding the current pull request, a new session was started with a specific request: take the current changes, put them into a pull request off dev, and set up a follow-up session to remove react-bootstrap.
Let's make a pull request for the existing work, and then start a new session for this react-bootstrap replacement work that will branch off this existing work here, and be a separate pull request to merge into dev after this one.
The app did exactly that:
- Created a pull request for the current changes off
dev. - Started a stacked session for the react-bootstrap removal, carrying context forward, creating a plan, and running it after approval.
- Opened a stacked pull request that followed the existing work.
A stack is a series of pull requests where each one targets the branch of the pull request below it, forming an ordered chain that eventually lands on the main branch. Here, both the sessions and their changes were stacked—each piece of work followed the previous one in a logical sequence rather than all being jammed together.

The final screenshot shows the structure clearly: the repository at the top, the initial "Frontend modernization" session, an abandoned first pull request attempt (marked with a red icon), a working pull request for the dev branch at the same level, and the draft pull request for the react-bootstrap changes nested below it.
Software development has never been entirely smooth, but keeping interdependent changes in an ordered chain is a significant improvement over wrestling with a single monolithic update. For anyone facing a similar modernization effort, this approach is worth trying.



