Ship Stacked Pull Requests on GitHub
Split a feature into dependent pull requests, review them, and merge the stack.
Introduction
30 Second Summary
When a big change arrives all at once, finding one risky detail can feel like searching an entire room for a missing key. Smaller pieces make progress easier to see.
In this project, you will split one feature into three stacked pull requests on GitHub. You will review each layer separately before merging the stack together.
What You'll Build
You'll open GitHub to see a data layer, logic layer, then page layer lined up in one reviewable stack.
By the end of this project, you'll have:
- A three-part feature stack you can review one layer at a time. Each pull request shows its position in the stack.
- A resilient approval flow where a review stays in place after unchanged code moves through an automatic rebase.
- A single stack merge that brings all three feature layers into your main branch together.
- Secret Mission: An optional challenge to push your skills further.
Do I need anything before starting?
You need a free GitHub account plus Git on your computer. The project guides you through installing the GitHub CLI plus its stack extension.
Before We Start
A stack of pull requests connects local commits to reviews on GitHub. Missing tools or an unnamed commit can derail the workflow before the first branch exists.
First, you'll prepare a terminal that can run Git commands. Then, you'll configure your commit identity.
You will finish with your GitHub account open in the browser.
In this step, get ready to:
- Confirm Git runs in your terminal.
- Configure your Git commit identity.
- Sign in to GitHub in your browser.
Check Git in your terminal
Your terminal gives you a place to run the commands that create branches and manage the stack. Checking Git now confirms that those commands are available.
- Press Cmd+Space on macOS or the Windows key on Windows to open system search.
- Type Terminal on macOS or PowerShell on Windows.
- Press Enter to launch the terminal.
- Check whether Git is installed by running this command:
git --version
What does this command check?
The git --version command asks the Git executable to report its installed version. A version line confirms that your terminal can reach Git.
✔️ I see a Git version
You're ready. Your terminal can reach Git for every branch operation ahead.
ⓧ Command not found
Git needs to be installed before your terminal can run its commands. The official installer selects the correct files for your operating system.
- Open the official Git install page in your browser.
- Choose the installer for your operating system.
- Complete the installation prompts.
- Return to the terminal from earlier.
- Confirm Git is available by running this command:
git --version
What confirms the installation?
This command checks whether the new Git installation is available to your terminal. A version line confirms that the installation worked.
You should now see a Git version in the terminal.
Git still unavailable?
- Close the terminal so it can refresh its command path.
- Reopen Terminal on macOS or PowerShell on Windows through your system search.
Ask for help with your operating system and installation result: Help me make Git available in my terminal.
Configure your Git identity
Git stores an author name and email address in every commit. Global configuration applies this identity to every repository you use on this computer.
- Enter the name you want Git to attach to your commits here: your name.
- Enter the email address you want Git to attach to your commits here: you@example.com.
- Save both values to your global Git configuration by running these commands:
git config --global user.name "[[GIT_NAME="your name"]]"
git config --global user.email [[GIT_EMAIL="you@example.com"]]
What do these commands change?
- The --global option stores each setting for your user account across all repositories.
- The user.name setting becomes the author name on your commits.
- The user.email setting becomes the author email on your commits.
- Check the saved values by running this command:
git config --list
What does this list show?
The git config --list command prints the settings Git can currently find. Your identity appears among those settings.
You should see entries beginning with user.name= and user.email=. Each entry should contain the value you supplied.
That is your commit identity locked in. Future commits can now show who created them.
Identity missing or incorrect?
- Run both configuration commands again if either entry is missing.
- Rerun the relevant configuration command with the correct value if an entry contains a typo.
Get help checking your configuration: Help me fix my Git identity settings.
Sign in to GitHub
Your GitHub account hosts the repository that reviewers see. A verified email address is required before you can create that repository.
- Choose the tab that matches your current GitHub account status.
I already have a GitHub account
Signing in uses your account credentials. GitHub handles them in the browser, so this project never asks you to paste a password into the terminal.
- Open the GitHub homepage in your browser.
- Select Sign in if GitHub asks you to authenticate.
- Enter your GitHub credentials.
- Complete any account verification prompt.
I need a GitHub account
A personal GitHub account gives you a place to host the practice repository. Email verification unlocks repository creation.
- Open the GitHub sign-up page in your browser.
- Follow the prompts to create your personal account.
- Verify your email address using the message GitHub sends you.
- Return to GitHub in your browser.
- Select Sign in if GitHub asks you to authenticate.
- Enter your new GitHub credentials.
Before you check, which GitHub username do you expect to see connected to this browser?
- Select your account avatar in the GitHub page header.
You should see your GitHub username in the account menu. This confirms that the browser is signed in to the account you will use for the project.
Can't see your username?
- Reload the GitHub page after completing account verification.
- Check your inbox for the verification message if you created a new account.
Get help with the sign-in state: Help me confirm my GitHub account is signed in.
Your local Git identity is ready for GitHub. Next, you'll create the practice repository and push its first commit.
Create a Practice Repository
Every stacked pull request needs a shared starting point. Without one, later feature branches can drift away from the same baseline.
This step gives the stack a small baseline in Git. You will publish its first commit to GitHub from a local repository.
In this step, get ready to:
- Create an empty GitHub repository.
- Commit a tiny starter page on main.
- Publish main to GitHub.
Create the empty GitHub repository
The GitHub repository becomes the online destination for your local work. Keeping it empty prevents starter files from creating a competing history.
- Switch back to the GitHub browser tab from earlier.
- Select the creation menu in the upper-right corner.
- Click New repository.
- Select your personal account under Owner.
- Enter stacked-prs-demo in the Repository name field.
- Choose Public under visibility.
- Keep every repository initialization option empty.
- Click Create repository.
Why keep the repository empty?
A generated README or license would create a separate commit on GitHub. An empty repository lets your local starter app become the single shared baseline.
That first half is in place. GitHub now has an empty destination for your local app.
- Copy the remote repository URL from the setup page.
- Record the copied URL here: https://github.com/your-username/stacked-prs-demo.git.
Build and commit the starter app
A small HTML page gives each later layer something concrete to extend. The platform tabs create the same index.html file with commands suited to your terminal.
macOS
- Create the stacked-prs-demo folder on your Desktop by running these commands:
cd ~/Desktop
mkdir stacked-prs-demo
cd stacked-prs-demo
git init -b main
What do these commands do?
- The first command moves your terminal to the Desktop.
- The next two commands create stacked-prs-demo and move your terminal into it.
- The final command initializes Git with main as the first branch.
- Create the starter page inside stacked-prs-demo by running this block:
cat > index.html <<'EOF'
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Stacked PRs Demo</title>
</head>
<body>
<!-- Keep the baseline small so later branches own each feature layer. -->
<h1>Stacked PRs Demo</h1>
<p>Ready for a stacked feature.</p>
</body>
</html>
EOF
What does this block do?
The shell writes every line between the markers into index.html. The page gives your repository a visible starting point.
Windows
- Create the stacked-prs-demo folder on your Desktop by running these commands in PowerShell:
cd ~/Desktop
mkdir stacked-prs-demo
cd stacked-prs-demo
git init -b main
What do these commands do?
- The first command moves your terminal to the Desktop.
- The next two commands create stacked-prs-demo and move your terminal into it.
- The final command initializes Git with main as the first branch.
- Create the starter page inside stacked-prs-demo by running this block:
@'
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Stacked PRs Demo</title>
</head>
<body>
<!-- Keep the baseline small so later branches own each feature layer. -->
<h1>Stacked PRs Demo</h1>
<p>Ready for a stacked feature.</p>
</body>
</html>
'@ | Set-Content -Path index.html -Encoding UTF8
What does this block do?
The PowerShell here-string holds the complete page. Set-Content writes it to index.html using UTF-8 encoding.
- Switch back to the browser from earlier.
- Press Cmd+O on macOS or Ctrl+O on Windows.
- Select Desktop/stacked-prs-demo/index.html in the file picker.
- Confirm the file selection to load the page.
You should see Stacked PRs Demo above the text Ready for a stacked feature. That visible page proves your baseline app works.
Don't see the starter page?
- Confirm that the selected file is Desktop/stacked-prs-demo/index.html.
- Check that your terminal prompt is inside stacked-prs-demo before rerunning your platform's file-creation block.
Help me fix my local starter page.
✔️ Awesome, I've got everything!
Great. Your starter page is saved inside stacked-prs-demo.
ⓧ I'd like to double check the full code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Stacked PRs Demo</title>
</head>
<body>
<!-- Keep the baseline small so later branches own each feature layer. -->
<h1>Stacked PRs Demo</h1>
<p>Ready for a stacked feature.</p>
</body>
</html>
- Stage the starter page and create its first commit by running:
git add .
git commit -m "First commit"
What do these commands do?
- The first command stages index.html for the next snapshot.
- The second command records that snapshot with the message First commit.
- Inspect the newest local commit by running:
git log --oneline -1
What does this check show?
The command condenses the newest commit into one line. It gives you the commit identifier plus its message.
You should see a short commit identifier followed by First commit.
Commit missing from the log?
- Confirm that the earlier commit command completed without an error.
- Check that Git already has your name and email from the project prerequisites.
Help me troubleshoot my missing first commit.
Push and inspect the first commit
Your commit currently exists only on your computer. Adding origin connects that local history to the empty GitHub repository.
- Connect the local repository to the URL you recorded by running:
git remote add origin [[YOUR_REPO_URL="https://github.com/your-username/stacked-prs-demo.git"]]
git remote -v
What do these commands do?
- The first command stores your GitHub repository under the remote name origin.
- The second command displays the saved remote for a quick accuracy check.
You should see your recorded repository URL listed for fetching and pushing.
Remote URL look wrong?
- Compare the displayed URL with the URL on your GitHub repository setup page.
- Confirm that the repository name ends with stacked-prs-demo.git.
Help me correct my Git remote.
A first push may ask you to confirm your GitHub identity. The prompt only authorizes Git to publish this repository.
- Prepare to complete any authentication prompt through the sign-in method Git presents.
Before you push, do you think the GitHub repository will still look empty after this command finishes?
- Publish main to GitHub by running:
git push -u origin main
What does this push do?
The command sends your local main branch to origin. The upstream setting links future pushes from local main to the same GitHub branch.
The push completes with your local branch connected to origin/main.
Push not completing?
- Complete the GitHub authentication flow if your terminal or browser is waiting for approval.
- Check that git remote -v shows the repository you created.
- Confirm that the GitHub repository is still empty before retrying the push.
Help me troubleshoot my first push.
Before you run these checks, what branch name should appear? What commit message should appear?
- Check the final local repository state by running:
git branch --show-current
git status --short
git log --oneline -1
What do these checks prove?
- The branch check identifies your current branch.
- The status check reveals any uncommitted files.
- The log check identifies the latest commit.
You should see main followed by no short-status output. The final line should end with First commit.
- Switch back to the GitHub repository page.
- Refresh the browser page.
- Confirm that the branch selector shows main.
- Confirm that index.html appears in the file list.
- Click commits above the file list.
- Click First commit.
You should see the commit page for First commit with index.html as its change. That is the shared baseline your entire stack builds on.
Your local app now has a clean home on GitHub. Next, you will install the GitHub CLI and prepare this repository for its first stack.
Set Up Your Pull Request Stack
Your tiny web app is already stored in GitHub. The next feature spans three layers. One giant pull request would make those layers harder to review.
In this step, you will install the GitHub CLI plus its stack extension. These tools manage a chain of stacked pull requests from your terminal.
In this step, get ready to:
- Install a compatible version of the GitHub CLI.
- Authenticate the GitHub CLI before installing its stack extension.
- Initialize stack management in your local repository.
Install the GitHub CLI
The stack quickstart requires GitHub CLI version 2.90.0 or later. A version check tells you whether the tool is ready or needs attention.
- Check your installed GitHub CLI version by running this command:
gh --version
What does this command do?
This command prints the installed GitHub CLI version. The first line gives you the version to compare with the project requirement.
✔️ I see version 2.90.0 or higher
Your installed version meets the requirement. GitHub CLI is ready to manage the stack extension.
ⓧ I see an older version
Your current installation needs an upgrade before it can follow the stacked pull request quickstart.
macOS
- Upgrade GitHub CLI with Homebrew by running this command:
brew upgrade gh
What does this command do?
Homebrew downloads the latest available GitHub CLI package. It replaces the older package while preserving your local Git configuration.
- Repeat the version check shown above.
- Confirm that the first line reports version 2.90.0 or higher.
Windows
- Upgrade GitHub CLI with WinGet by running this command:
winget upgrade --id GitHub.cli --source winget
What does this command do?
WinGet finds the GitHub CLI package in its configured source. It upgrades the package to the latest available release.
- Repeat the version check shown above.
- Confirm that the first line reports version 2.90.0 or higher.
Still seeing the older version?
Restart the terminal from earlier after the upgrade finishes. This reloads the command path used by your shell.
If the version stays below the requirement, use the official GitHub CLI installation guide for your operating system.
Help me diagnose why my GitHub CLI version did not update.
ⓧ Command not found
GitHub CLI is missing from your command path. Install it with the package manager for your operating system.
macOS
- Install GitHub CLI with Homebrew by running this command:
brew install gh
What does this command do?
Homebrew downloads the GitHub CLI package. It also places the gh command on your shell path.
- Repeat the version check shown above.
- Confirm that the first line reports version 2.90.0 or higher.
Windows
- Install GitHub CLI with WinGet by running this command:
winget install --id GitHub.cli --source winget
What does this command do?
WinGet downloads the official GitHub CLI package. The installer makes the gh command available in Windows terminals.
- Repeat the version check shown above.
- Confirm that the first line reports version 2.90.0 or higher.
Installation command unavailable?
Use the official GitHub CLI installation guide if your computer does not have the package manager shown here. Choose the precompiled installer for your operating system.
Help me install GitHub CLI on my computer.
Authenticate and install the stack extension
The stack extension uses the account authenticated through GitHub CLI. The browser flow connects the terminal to the GitHub account you already use in your browser.
- Start browser-based authentication by running this command:
gh auth login --web
What does this command do?
This command starts GitHub CLI's web authentication flow. GitHub CLI stores the resulting authentication token in your system credential store when one is available.
- Keep the suggested GitHub host when the terminal asks where to authenticate.
- Keep the suggested Git protocol when the terminal asks how to perform Git operations.
- Copy the one-time code if the terminal displays one.
- Press Enter when the terminal asks you to continue in your browser.
- Approve access for GitHub CLI in the browser.
- Return to the terminal from earlier after the browser confirms authorization.
The browser flow is complete when your terminal reports a successful login. Your terminal can now act through your GitHub account.
- Verify the active account by running this command:
gh auth status
What does this command do?
This command tests the authentication state for each known GitHub host. It also identifies the active account that future GitHub CLI commands use.
You'll see your GitHub host plus an active authenticated account. That confirms your terminal can access the repository through GitHub CLI.
Authentication not active?
Repeat the browser flow if authorization was closed before completion. Make sure the browser uses the same GitHub account that owns stacked-prs-demo.
Help me troubleshoot GitHub CLI authentication.
A GitHub CLI extension adds commands without changing the app in index.html. The stack extension handles local stack tracking plus later submission and merging operations.
- Install the official stack extension by running this command:
gh extension install github/gh-stack
What does this command do?
This command downloads the gh-stack extension from GitHub. It adds stack-management commands beneath gh stack.
- Wait for the extension installation to finish.
You'll see the terminal report that the extension was installed. The next command proves that its stack features are available.
Extension installation failed?
Confirm that the authentication check identifies an active account. Check your network connection if the extension cannot download from GitHub.
Help me troubleshoot the stack extension installation.
Initialize and inspect the stack
Stack initialization creates local tracking information for the repository. Your existing main branch remains the trunk that future layers build on.
- Initialize stack management in the current stacked-prs-demo repository by running this command:
gh stack init
What does this command do?
This command creates local tracking information for a stack. It uses the repository's default branch as the trunk.
It also enables Git's recorded conflict resolutions for future rebases. That helps repeated stack updates reuse a resolution you already made.
- Choose the option to use the current main branch when the prompt offers it as the first layer.
- Finish the prompt without naming another branch.
Your repository now has local stack tracking while remaining on main. No pull requests have been created.
Before you inspect the stack, what branch do you expect to anchor the listing?
- Display the current stack in a compact format by running this command:
gh stack view --short
What does this command show?
The compact view prints one line for each tracked branch. It shows the stack order without opening the full-screen interface.
You'll see a compact stack listing anchored to main. No pull request links appear because you have not submitted a stack.
Stack view not available?
Confirm that your terminal is still inside the local stacked-prs-demo repository. Repeat the extension installation if the terminal does not recognize the stack command.
Help me troubleshoot my local stack initialization.
Your GitHub account and local repository are ready for stacked work. Next, you'll turn the feature into three focused layers that reviewers can inspect separately.
Build and Push the Feature Stack
Your local repository is synchronized with GitHub. The stack extension is ready to track each dependent branch.
A complete feature usually crosses several layers. You will separate those layers into three stacked pull requests so reviewers can inspect one focused change at a time.
In this step, get ready to:
- Build the data layer on feature/data.
- Add the logic layer on feature/logic.
- Add the page layer on feature/page before submitting the stack.
Build the data layer
The bottom layer contains the feature data without any display code. Every branch above it inherits this commit.
- Create the first tracked branch above main by running this command:
gh stack init feature/data
What does this command do?
The gh stack init command starts a feature stack with feature/data directly above main.
The command also checks out the new branch. Your next commit therefore belongs to the bottom layer.
- Create data.js inside the open stacked-prs-demo repository by running this terminal command:
cat > data.js <<'EOF'
// Keep the feature content separate from its display logic.
const featureLayers = [
{
title: "Data",
detail: "Stores the feature content."
},
{
title: "Logic",
detail: "Turns the content into cards."
},
{
title: "Page",
detail: "Displays the finished feature."
}
];
window.featureLayers = featureLayers;
EOF
What does this code do?
- The featureLayers array stores the three pieces of the feature.
- Each object keeps a layer title beside the detail shown to the visitor.
- The window.featureLayers assignment makes the data available to the logic layer.
- Record the completed data layer in Git by running these commands:
git add data.js
git commit -m "Add feature data"
gh stack view
What should you see?
The commit records only data.js on feature/data.
The stack view now lists main as the trunk. It shows feature/data as the active layer above it.
Data branch missing from the stack?
Check that the branch command completed before you created data.js. A failed branch command can leave the commit on main.
Use the stack view to confirm your current layer. Help me diagnose why feature/data is missing from my stacked pull request workflow.
✔️ Awesome, I've got everything!
Your data layer is committed on the bottom branch. The next branch can build directly on it.
ⓧ I'd like to double check the full code
Compare your saved data.js file with this complete reference.
// Keep the feature content separate from its display logic.
const featureLayers = [
{
title: "Data",
detail: "Stores the feature content."
},
{
title: "Logic",
detail: "Turns the content into cards."
},
{
title: "Page",
detail: "Displays the finished feature."
}
];
window.featureLayers = featureLayers;
Add the logic and page layers
The middle layer reads the feature data. Its branch starts from feature/data so the logic can use everything below it.
- Create the middle branch above feature/data by running this command:
gh stack add feature/logic
How does the branch stay connected?
The gh stack add command creates feature/logic from your current data branch.
This dependency later makes the logic pull request target feature/data.
- Create app.js inside stacked-prs-demo by running this terminal command:
cat > app.js <<'EOF'
// Turn each data entry into a visible list item.
function renderFeatureStack() {
const list = document.querySelector("#feature-stack");
window.featureLayers.forEach((layer) => {
const item = document.createElement("li");
item.innerHTML = `<strong>${layer.title}</strong>: ${layer.detail}`;
list.appendChild(item);
});
}
renderFeatureStack();
EOF
What does this code do?
- The renderFeatureStack() function finds the page list.
- The loop converts every data object into a list item.
- The final function call renders all three items when the script loads.
- Record the logic layer before moving higher in the stack by running these commands:
git add app.js
git commit -m "Add feature logic"
gh stack view
What should you see?
The stack now contains two feature branches. feature/logic appears above feature/data as the active layer.
Logic layer in the wrong place?
Check that feature/data was active when you added feature/logic. The new branch always sits above the current layer.
Use the stack view before creating another branch. Help me fix the order of my data and logic branches.
✔️ Awesome, I've got everything!
Your logic layer is committed above the data layer. The page can now consume both files.
ⓧ I'd like to double check the full code
Compare your saved app.js file with this complete reference.
// Turn each data entry into a visible list item.
function renderFeatureStack() {
const list = document.querySelector("#feature-stack");
window.featureLayers.forEach((layer) => {
const item = document.createElement("li");
item.innerHTML = `<strong>${layer.title}</strong>: ${layer.detail}`;
list.appendChild(item);
});
}
renderFeatureStack();
The top layer changes the page that visitors see. It inherits both lower commits without adding those files to its own focused diff.
- Create the top branch above feature/logic by running this command:
gh stack add feature/page
Where does the page branch belong?
The new feature/page branch sits directly above feature/logic.
This placement gives the page access to both app.js and data.js.
- Replace the starter page in index.html by running this terminal command:
cat > index.html <<'EOF'
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Stacked PR Demo</title>
</head>
<body>
<!-- The page layer provides a target for the logic layer. -->
<main>
<h1>Feature Stack</h1>
<p>One feature delivered in three reviewable layers.</p>
<ul id="feature-stack"></ul>
</main>
<script src="data.js"></script>
<script src="app.js"></script>
</body>
</html>
EOF
What does this page do?
- The feature-stack list gives the logic layer a place to render each item.
- The page loads data.js before app.js so the data exists when rendering begins.
- The heading makes the completed three-layer feature visible in the browser.
- Record the page layer at the top of the stack by running these commands:
git add index.html
git commit -m "Add feature page"
gh stack view
What should you see?
The stack view now lists feature/page above feature/logic.
Your current branch remains feature/page at the top of the three-layer stack.
Page commit showing extra files?
The page commit should contain the index.html change. The lower files appear in the branch history because the page depends on them.
Check the stack order before submitting. Help me verify that my page commit belongs only to feature/page.
✔️ Awesome, I've got everything!
Your page layer is committed at the top. All three feature layers are ready to become pull requests.
ⓧ I'd like to double check the full code
Compare your saved index.html file with this complete reference.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Stacked PR Demo</title>
</head>
<body>
<!-- The page layer provides a target for the logic layer. -->
<main>
<h1>Feature Stack</h1>
<p>One feature delivered in three reviewable layers.</p>
<ul id="feature-stack"></ul>
</main>
<script src="data.js"></script>
<script src="app.js"></script>
</body>
</html>
Submit and inspect the stack
Submitting publishes every tracked branch. The extension also creates each pull request with the branch below it as the base.
Before you submit, which branch do you expect each pull request to target?
- Push the branches before creating the linked pull requests by running this command:
gh stack push
What does this command do?
The gh stack push command publishes every active branch in the stack to the remote repository.
It preserves the local dependency order. Pull requests are created in the next command.
- Create the three pull requests as one linked stack by running this command:
gh stack submit --auto --open
How does submission work?
- The gh stack submit command creates or updates a pull request for every branch.
- The --auto flag uses generated pull request titles without opening the interactive editor.
- The --open flag marks the pull requests as ready for review.
You should see confirmation that three pull requests were created. Their bases follow the same bottom-to-top order as your local stack.
Before you inspect the final status, do you expect the terminal to show one pull request or three linked pull requests?
- Inspect the submitted stack by running this command:
gh stack view
What should the stack view show?
- The bottom layer shows feature/data with its pull request link.
- The middle layer shows feature/logic with its pull request link.
- The top layer shows feature/page with its pull request link.
- Copy the bottom pull request link from the terminal output.
- Switch to your signed-in GitHub browser window.
- Paste the link into the address bar before pressing Enter.
- Use the stack header to confirm that the pull request occupies the bottom position.
- Use the stack map to open the middle pull request.
- Confirm that feature/logic targets feature/data.
- Use the stack map to open the top pull request.
- Confirm that feature/page targets feature/logic.
You should see all three open pull requests in the stack map. The bottom request targets main.
That is the full feature stack working. GitHub now presents three focused reviews while preserving the complete feature order.
Pull requests missing from the stack?
Confirm that all three branches appear in the terminal stack view. A branch without a commit cannot provide a separate review layer.
Check that submission completed without an authentication or network error. Help me troubleshoot missing pull requests after submitting my stack.
Your three review layers are live on GitHub. Next, you will approve the bottom pull request before changing a higher layer to test how the stack preserves that review.
Preserve Approval Through a Rebase
Your three stacked pull requests are now open on GitHub. Each layer has a focused diff that can be reviewed on its own.
The test now is whether the bottom layer keeps its approval while the stack changes above it. You’ll update the page layer before using a rebase to synchronize the stack.
In this step, get ready to:
- Get the bottom pull request approved.
- Add an update to the page layer.
- Synchronize the stack before checking the approval.
Approve the bottom pull request
An approval records a review of one pull request layer. Pull request authors cannot approve their own pull requests, so another GitHub user must review the bottom layer.
- Switch back to the GitHub browser tab from earlier.
- Click Pull requests under the repository name.
- Select the pull request from feature/data into main.
- Copy the pull request URL from your browser address bar.
- Send the URL to another GitHub user who can access the repository.
Why use another reviewer?
GitHub prevents pull request authors from approving their own work. A separate reviewer creates the approval that you need for this experiment.
- Ask your reviewer to click Files changed.
- Ask your reviewer to inspect the changes in data.js.
- Ask your reviewer to click Review changes.
- Ask your reviewer to select Approve.
- Ask your reviewer to click Submit review.
That review is in place. Your data layer now has an approval that the stack must preserve.
Update the page layer
The top branch owns index.html, so a page change belongs on feature/page. Keeping the edit on its owning branch preserves the boundaries between layers.
- Open stacked-prs-demo/index.html in the code editor you used to build the page layer.
- Locate the existing section that renders the stacked feature.
- Add a new paragraph containing Approval survived the stack update. inside that section.
- Save index.html.
- Return to the terminal from earlier.
- Review the saved update by running this command:
git diff
What does this command show?
The git diff command compares your saved files with the staging area. It lets you inspect the page update before committing it.
You’ll see a diff for index.html. The added paragraph appears among the changed lines.
No page update in the diff?
Confirm that you saved index.html inside the stacked-prs-demo repository. Check that the editor is showing the file from feature/page.
Help me find why my saved change does not appear in Git diff.
- Commit the page-layer update by running these commands:
git add .
git commit -m "helpful-commit-message"
What do these commands do?
- The git add . command stages the saved page update.
- The git commit -m "helpful-commit-message" command stores the staged update in the history of feature/page.
- Confirm that Git reports a new commit with one changed file.
The higher-layer update is now committed on feature/page. The approved data-layer commit remains unchanged.
Commit missing the page update?
Check the earlier diff for index.html. An empty commit result usually means the file was not saved or the change was already committed.
Help me troubleshoot my missing page-layer commit.
Synchronize the stack
A cascading rebase checks the branches from the trunk upward. The stack extension then pushes the synchronized branches with safeguards against overwriting unexpected remote work.
Before you run this, make a quick prediction about whether the bottom approval will remain after synchronization.
- Rebase the stack before pushing the update by running these commands:
gh stack rebase
gh stack push
How is the stack synchronized?
- The gh stack rebase command checks every branch against the layer below it.
- The gh stack push command updates the remote branches using --force-with-lease safeguards.
- GitHub preserves approvals when a stack rebase leaves the reviewed code unchanged.
- Confirm that the terminal finishes the rebase without reporting a conflict.
- Confirm that the terminal finishes pushing the stack.
The remote stack now includes the page-layer update. All three pull requests remain open in the same order.
Did the rebase pause?
Read the conflicted filenames printed by the extension. Resolve each marked section in the listed file before following the continuation command shown in the terminal.
Help me resolve my stacked pull request rebase conflict.
Before you refresh GitHub, predict whether the approval follows the unchanged bottom-layer code through the stack update.
- Switch back to the GitHub browser tab from earlier.
- Select the feature/page pull request from the stack header.
- Click Files changed.
- Confirm that the index.html diff contains Approval survived the stack update..
- Select the feature/data pull request from the stack header.
- Refresh the pull request page.
- Confirm that the reviewer’s approval remains visible.
There it is. The page layer changed while the approved data-layer code stayed intact, so GitHub kept the bottom review in place.
Your stack has survived a real review cycle without throwing away valid approval. Next, you’ll merge all three layers together.
Merge the Stack
Your GitHub stack has passed its most important test. The approval on feature/data survived the higher-layer update and automatic rebase.
Your three stacked pull requests still form one dependency chain. This step lands the data layer, logic layer, and page layer on main in dependency order.
In this step, get ready to:
- Review the merge state of all three pull requests.
- Merge the complete stack as one operation.
- Confirm the feature on the repository's main branch.
Review merge readiness
A stack merge is an all-or-nothing operation. If one selected pull request cannot merge, GitHub leaves the whole group unmerged.
Before you run the check, which three open pull requests do you expect the active stack to list?
- Display the active stack in your terminal by running this command:
gh stack view
What does this command show?
- The gh stack view command reads the active stack tracked by the GitHub CLI extension.
- The branch order shows how each pull request depends on the layer below it.
- The pull request statuses reveal whether each layer is still open before the merge.
You should see feature/data at the bottom, feature/logic in the middle, and feature/page at the top. Each branch should still point to an open pull request.
Is a branch missing from the stack?
- Confirm that your terminal is still inside the local stacked-prs-demo repository.
- Confirm that the current branch is feature/page.
Use this if the displayed stack does not contain all three branches: Help me diagnose why gh stack view is missing a branch from my three-layer stack.
Complete the stack
Merging three pull requests in one command can feel final. The operation is atomic, so a blocked layer leaves every pull request open.
Before you merge, do you expect GitHub to land the page layer first or follow the dependency order from data to page?
- Merge the active stack without additional prompts by running this command:
gh stack merge --yes --squash
How does the stack merge work?
- The gh stack merge command selects the active local stack.
- The --yes flag confirms the operation without an interactive prompt.
- The --squash flag uses the squash merge method for the selected pull requests.
- GitHub merges feature/data first. It follows with feature/logic and feature/page.
You should see the merge operation finish without a reported failure. That's the stack shipped: all three reviewed layers now land together on main.
Was the stack merge blocked?
- Return to any pull request that GitHub reports as blocked.
- Resolve the reported review or status-check requirement.
- Select Rebase stack in the merge box if GitHub reports that the stack history is no longer linear.
- Wait for the rebase to finish before rerunning the merge command.
Use this if the merge command reports a requirement that you cannot identify: Help me understand why my GitHub stack merge is blocked.
Verify the completed feature
A successful merge leaves evidence in the pull request history and on main. First, confirm that every reviewed layer records its merged state.
- Return to the feature/data pull request page from earlier.
- Confirm that the bottom pull request is marked as merged.
- Use the stack header to open the feature/logic pull request.
- Confirm that the middle pull request is marked as merged.
- Use the stack header to open the feature/page pull request.
- Confirm that the top pull request is marked as merged.
All three pull requests now show the same completed story. The retained approval on the bottom layer led to one merged stack.
Before you check the repository, which three feature files do you expect to find together on main?
- Return to the stacked-prs-demo repository page from earlier.
- Use the branch selector above the file list to choose main.
- Confirm that the file list includes data.js, app.js, and index.html.
- Open index.html from the file list.
- Confirm that it contains the merged page-layer feature and the higher-layer update.
You can now see the data, logic, and page layers together on main. The large change has reached its destination through three focused pull requests.
Secret mission
Audit Your Stack's Review Boundaries
Revisit the merged stack as a reviewer. Trace each dependency to prove every pull request owns one clear decision.
Clean Up Your Resources
Clean Up Your Resources
Your project is complete, so choose whether to keep it as a reference, pause your work, or remove it entirely. The repository and local files do not create ongoing compute costs.
Resources you used:
- The GitHub repository stacked-prs-demo with its merged pull request history.
- The local Git repository folder stacked-prs-demo with the completed app files.
- The merged branches feature/data, feature/logic, and feature/page if your repository settings kept them after the merge.
Keep everything running
Your completed project needs no running process. Choose this option to preserve the repository as a reference for future stacked pull requests.
- Keep the GitHub repository stacked-prs-demo with its pull request history.
- Keep the local repository folder stacked-prs-demo with the completed app.
- Return to the stacked-prs-demo repository in the GitHub browser tab from earlier.
- Check the repository branch list for feature/data, feature/logic, and feature/page.
- Delete each merged feature branch that is still listed.
- Confirm that main is the only remaining branch.
Pause - I'll come back to this later
Pausing means leaving both repository copies intact. There is no server process to stop.
- Close the GitHub browser tab for stacked-prs-demo.
- Close the terminal window that is currently in the local stacked-prs-demo repository.
Your completed code and pull request history remain available when you return.
Delete - I don't want to use this again
Remove the GitHub repository first. Remove the local repository folder after GitHub confirms the deletion.
Delete the GitHub repository.
- Return to the stacked-prs-demo repository in the GitHub browser tab from earlier.
- Go to the repository settings page.
- Use the general settings area to find the repository deletion controls.
- Choose the option that permanently deletes the repository.
- Enter stacked-prs-demo when GitHub asks you to confirm the repository name.
- Confirm the permanent deletion.
- Check your GitHub repository list for stacked-prs-demo.
You should no longer see stacked-prs-demo in your GitHub repository list. This deletion also removes any remaining remote feature branches.
Delete the local repository.
- Close the terminal window that is currently in the local stacked-prs-demo repository.
- Find the local stacked-prs-demo folder in the location you used during the project.
- Delete the stacked-prs-demo folder using Finder on macOS or File Explorer on Windows.
- Check the folder's original location for stacked-prs-demo.
You should no longer see the local stacked-prs-demo folder.
Nice Work!
Nice Work!
You shipped a complete three-layer feature to GitHub through three stacked pull requests. Each layer stayed small enough to review before the full stack landed on main.
You've learned how to:
- Split one feature into three dependent pull requests for the data, logic, and page layers.
- Confirm a retained approval on the bottom pull request after an automatic rebase.
- Merge the complete stack into main with the finished feature live in your GitHub repository.
- Extend the project through an optional Secret Mission to push your stacked pull request skills further.
Ready to quiz yourself?