Simulate a Team Git Workflow
Practice branching, pull requests, and rebasing in a solo team simulation.
Introduction
30 Second Summary
When you join a development team, you won't be coding alone. You'll be sharing a codebase with teammates, and employers specifically test whether you can handle branching, merging, and cleaning up messy commit history.
In this project, you will simulate a full team Git workflow using GitHub. You'll create feature branches, write conventional commit messages, resolve merge conflicts, open pull requests, and use interactive rebase to clean up your history.
What You'll Build
A GitHub repository that demonstrates the professional Git workflow skills interviewers test for at the intermediate level.
By the end of this project, you'll have:
- A public GitHub repository with multiple merged pull requests showing a professional commit history.
- Hands-on experience creating feature branches, writing conventional commits, and resolving merge conflicts.
- A squashed, clean feature branch merged via interactive rebase and pull request.
- Secret Mission: Use git stash and cherry-pick to rescue misplaced work from the wrong branch.
Are there any prerequisites?
You'll need a GitHub account and Git installed on your computer. Both are confirmed as part of your learner environment.
No prior experience with branching or pull requests is required. This project teaches those skills from scratch.
Set Up Your Tools and Repository
Every professional Git workflow starts with two things: a properly configured identity and a shared repository. Your commit identity is what appears in your team's history, so getting it right from the start matters.
In this step, you will install Visual Studio Code, configure your Git name and email, and push your first commit to a new GitHub repository.
In this step, get ready to:
- Install Visual Studio Code.
- Configure your Git identity.
- Create and push a repository to GitHub.
Install Visual Studio Code
VS Code is the code editor you will use for the rest of this project. It has a built-in terminal and highlights merge conflict markers, which will be helpful later.
- Open your web browser and navigate to the VS Code download page:
- https://code.visualstudio.com/Download
- Download the installer for your operating system (the page auto-detects it).
- Run the installer and follow the prompts to complete the installation.
What does the installer do?
The VS Code installer adds a code command to your system PATH. This lets you open files and verify your installation from any terminal.
- Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
- Type Visual Studio Code and press Enter to open it.
- Open the integrated terminal by pressing Ctrl+` (the backtick key, usually above Tab).
- Verify your installation by running this command:
code --version
✔️ I see a version number
VS Code is installed and ready. You will use this terminal for the rest of the project.
ⓧ Command not found
The code command was not added to your PATH. Try these fixes:
- Close and reopen VS Code completely, then try the command again in a new terminal.
- On macOS, open the Command Palette with Cmd+Shift+P, type Shell Command: Install 'code' command in PATH, and select it.
- On Windows, re-run the installer and ensure the "Add to PATH" option is checked.
After applying the fix, close and reopen the terminal, then run code --version again.
Configure Git and create your project
Git uses your name and email to stamp every commit you make. This identity is what teammates see in the project history.
- Set your Git username by running this command:
git config --global user.name "[[YOUR_GIT_NAME="Your Name"]]"
- Set your Git email by running this command:
git config --global user.email "[[YOUR_GIT_EMAIL="your-email@example.com"]]"
What do these commands do?
The --global flag applies these settings to every Git repository on your machine. Your name and email will appear on every commit you make from now on.
- Move to your Desktop by running this command:
cd ~/Desktop
- Create your project folder and move into it by running these commands:
mkdir team-git-workflow-demo
cd team-git-workflow-demo
- Initialize a Git repository in this folder by running:
git init
You should see a message saying Initialized empty Git repository followed by your folder path.
- Open this project folder in VS Code by running:
code .
Stay in the integrated terminal
After running code ., a new VS Code window opens with your project folder loaded. Use the integrated terminal in that new window (Ctrl+`) for all remaining commands.
Now create the project's first file. This README.md describes what the repository is about.
- In VS Code, click File in the top menu bar.
- Click New File.
- Type README.md as the file name and press Enter.
- Paste the following content into the file:
# Team Git Workflow Demo
A project demonstrating professional Git workflow practices.
What is a README?
A README.md file is the front page of your repository on GitHub. It tells visitors what the project does and how to use it. Markdown formatting (the # for headings) makes it display nicely on the web.
- Save the file with Cmd+S (macOS) or Ctrl+S (Windows).
- Stage and commit the file by running these commands in the integrated terminal:
git add .
git commit -m "docs: add project README"
git branch -M main
What do these commands do?
The git add . stages all new files for commit. The git commit -m saves a snapshot with a message describing the change.
The git branch -M main renames the default branch to main so it matches what GitHub expects.
Next, create a repository on GitHub to host your project remotely.
- Open github.com in your browser and sign in.
- In the upper-right corner, click the + icon.
- Click New repository.
- Type team-git-workflow-demo in the Repository name field.
- Select Public for visibility.
- Leave the Add a README file option unchecked (you already created one locally).
- Click Create repository.
GitHub shows a quick setup page with your repository URL. Copy the HTTPS URL from this page.
- Connect your local project to GitHub and push your commit by running these commands:
git remote add origin [[YOUR_REPO_URL="https://github.com/your-username/team-git-workflow-demo.git"]]
git push -u origin main
What does push do?
The git remote add origin command connects your local repository to the GitHub repository. The git push -u origin main uploads your commit to GitHub and sets origin/main as the default upstream branch.
Push failed or asked for authentication?
If Git asks for credentials, GitHub requires a Personal Access Token (PAT) or SSH key instead of a password. Follow the prompts in your browser if a sign-in window appears, or visit GitHub's authentication docs to set up a token.
If you see error: remote origin already exists, you may have run the command twice. That is fine and you can proceed to the push step.
help me troubleshoot my git push to GitHub
Verify your setup on GitHub
- Refresh your repository page on GitHub.
- You should see your README.md file listed with the heading "Team Git Workflow Demo" rendered on the page.
- Confirm your commit identity by running this command in VS Code's terminal:
git log --oneline
You should see one commit with your docs: add project README message. The author matches the name and email you configured.
✔️ Awesome, I've got everything!
Great. Double check you have saved your README.md and that your GitHub page shows the rendered content.
ⓧ I'd like to double check the full code
Here is the complete README.md file you should have:
# Team Git Workflow Demo
A project demonstrating professional Git workflow practices.
Your environment is ready and your first commit is live on GitHub. Next up, you will create feature branches and practice writing professional conventional commits.
Create Feature Branches with Conventional Commits
Your repository is live on GitHub with a single commit. In a real team, developers never work directly on the main branch. Instead, each new feature gets its own isolated branch where changes can be developed and reviewed before merging.
In this step, you will create two feature branches and practice writing conventional commits. This commit message format is the standard that professional teams use to keep their history readable and enable automated tooling.
In this step, get ready to:
- Create a feature branch and build a simple HTML page with two conventional commits.
- Create a second feature branch from main with its own commit.
- Push both branches to GitHub.
Create a feature branch and build a simple HTML page
Feature branches follow the naming pattern feature/short-description. This keeps branches organized and tells teammates what the branch is for at a glance.
- In VS Code's integrated terminal, create and switch to a new feature branch by running this command:
git checkout -b feature/add-homepage
What does this command do?
The -b flag tells Git to create a new branch AND switch to it in one step. Without -b, Git would try to switch to an existing branch called feature/add-homepage and fail.
- Confirm you are on the new branch by running:
git branch
You should see feature/add-homepage highlighted with an asterisk, meaning it is your active branch.
Now you will create your first HTML file and commit it using the conventional commit format.
- In VS Code's **Explorer** sidebar, click the **New File...** button (the file icon with a plus sign).
- Type index.html and press **Enter**.
- Paste the following HTML boilerplate into the file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Team Git Workflow Demo</title>
</head>
<body>
</body>
</html>
What does this code do?
This is a standard HTML boilerplate. It sets up the document structure, character encoding, and viewport for responsive display. The <body> is intentionally empty because you will add content in the next commit.
- Save the file with **Cmd+S** (macOS) or **Ctrl+S** (Windows).
- Stage and commit the file by running these commands in the terminal:
git add index.html
git commit -m "feat: add HTML boilerplate for homepage"
What is a conventional commit?
Conventional commits follow the format type: description. Common types include feat (new feature), fix (bug fix), and docs (documentation changes).
This format is what professional teams use to keep their Git history scannable. It also enables automated changelog generation and semantic versioning.
You should see a message confirming the commit was created. Now add content to the page for your second commit.
- In index.html, find the empty <body> tags.
- Add a heading and paragraph between them so the body looks like this:
<body>
<h1>Welcome to Our Project</h1>
<p>This project demonstrates professional Git workflow practices including branching, pull requests, and interactive rebase.</p>
</body>
- Save the file with **Cmd+S** (macOS) or **Ctrl+S** (Windows).
- Stage and commit this change with a second conventional commit by running:
git add index.html
git commit -m "feat: add hero section with welcome message"
You now have two commits on your feature/add-homepage branch. Each commit captures one logical change with a clear message.
- Verify your commit history by running:
git log --oneline
You should see two commits with the messages feat: add hero section with welcome message and feat: add HTML boilerplate for homepage listed in reverse chronological order.
Don't see both commits?
Make sure you saved index.html before each git add command. Git stages the file as it exists on disk at that moment.
If your commit message has a typo, that is fine for now. The important thing is that two commits appear in the log.
help me debug my git commit history
✔️ Awesome, I've got everything!
Great. Double check you have saved index.html before moving on.
ⓧ I'd like to double check the full code
Here is the full index.html file at this point:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Team Git Workflow Demo</title>
</head>
<body>
<h1>Welcome to Our Project</h1>
<p>This project demonstrates professional Git workflow practices including branching, pull requests, and interactive rebase.</p>
</body>
</html>
Create a second feature branch from main
In a team environment, multiple features are developed in parallel. Each branch starts from main so it does not include unfinished work from other branches.
- Switch back to the main branch by running:
git checkout main
- Create and switch to a second feature branch by running:
git checkout -b feature/add-about-page
Notice that index.html disappears from the Explorer sidebar. That file only exists on the feature/add-homepage branch. This is branch isolation in action.
- In VS Code's **Explorer** sidebar, click the **New File...** button.
- Type about.html and press **Enter**.
- Paste the following HTML into the file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>About - Team Git Workflow Demo</title>
</head>
<body>
<h1>About</h1>
<section>
<h2>Bio</h2>
<p>A developer learning professional Git workflows for team collaboration.</p>
</section>
</body>
</html>
What does this code do?
This about page uses a <section> element to group the bio content semantically. It is a simple page, but the point here is practicing the Git workflow, not building a complex website.
- Save about.html with **Cmd+S** (macOS) or **Ctrl+S** (Windows).
- Stage and commit by running:
git add about.html
git commit -m "feat: add about page with bio section"
You should see a confirmation that the commit was created on feature/add-about-page.
Seeing 'nothing to commit'?
This means about.html was not saved before you ran git add. Save the file first, then run both commands again.
help me fix my git commit
✔️ Awesome, I've got everything!
Great. Double check you have saved about.html before moving on.
ⓧ I'd like to double check the full code
Here is the full about.html file at this point:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>About - Team Git Workflow Demo</title>
</head>
<body>
<h1>About</h1>
<section>
<h2>Bio</h2>
<p>A developer learning professional Git workflows for team collaboration.</p>
</section>
</body>
</html>
Push both branches to GitHub
Your branches only exist on your local machine right now. Pushing them to GitHub makes them available for pull requests and collaboration.
- Switch to the homepage branch and push it to GitHub by running these commands:
git checkout feature/add-homepage
git push -u origin feature/add-homepage
What does -u origin mean?
The -u flag sets up a tracking relationship between your local branch and the remote branch. After this, you can just run git push without specifying the remote and branch name every time.
The word origin is the default name Git gives to the remote repository you cloned or pushed to originally.
- Switch to the about branch and push it by running:
git checkout feature/add-about-page
git push -u origin feature/add-about-page
- Verify both branches exist remotely by running:
git branch -a
You should see your local branches plus remote tracking branches listed as remotes/origin/feature/add-homepage and remotes/origin/feature/add-about-page.
- Open your repository on GitHub in your browser. Click the branch dropdown (it says **main**) to confirm both feature branches appear in the list.
Branches not showing on GitHub?
Make sure the git push commands completed without errors. If you see a permissions error, confirm you are signed into the correct GitHub account that owns the repository.
If the push succeeded but you do not see branches in the dropdown, try refreshing the GitHub page.
help me push my branches to GitHub
You now have two feature branches with clean, conventional commit messages pushed to GitHub. Next up, you will deliberately create a merge conflict between these branches and learn how to resolve it.
Create and Resolve a Merge Conflict
Your two feature branches are ready on GitHub. In a real team, two developers would be working on these branches at the same time.
When two branches modify the same part of the same file, Git cannot automatically decide which version to keep. This creates a merge conflict. In this step, you will deliberately trigger a conflict and resolve it by hand.
In this step, get ready to:
- Create conflicting edits to README.md on both feature branches.
- Merge the first branch cleanly, then trigger a conflict with the second.
- Resolve the conflict manually and commit the fix.
Create conflicting changes
To trigger a merge conflict, both branches need to edit the same lines of the same file. You will add a "Features" section to README.md on each branch, but with different content.
- Switch to your first feature branch by running this command:
git checkout feature/add-homepage
- Open README.md in VS Code. Replace the entire file content with:
# Team Git Workflow Demo
A project demonstrating professional Git workflow practices.
## Features
- Homepage with hero section
What does this edit do?
You are adding a "## Features" heading and one bullet point that describes the homepage. The other branch will add a different bullet under the same heading. Git will see both edits touching the same area and flag a conflict.
- Save README.md.
- Commit this change by running:
git commit -am "docs: add features list to README"
- Now switch to your second feature branch by running:
git checkout feature/add-about-page
- Open README.md in VS Code again. Replace the entire file content with:
# Team Git Workflow Demo
A project demonstrating professional Git workflow practices.
## Features
- About page with bio
Why is this different from the first branch?
This version lists "About page with bio" under the same "## Features" heading. Both branches modified the same section of the same file starting from the same original content. When Git tries to combine them, it will not know which version to keep.
- Save README.md.
- Commit this change by running:
git commit -am "docs: add features list to README"
- Verify both branches have a new commit by running git log --oneline. You should see the "docs: add features list to README" commit at the top.
Commit says nothing to commit?
Make sure you saved README.md before running the commit command. The -a flag only stages changes to files that are already tracked AND saved to disk.
Help me figure out why my commit says nothing to commit.
Merge the first branch into main and trigger the conflict
Now you will merge both branches into main, one at a time. The first merge will succeed cleanly because main has not changed. The second merge will fail because it conflicts with what the first merge added.
- Switch back to main by running:
git checkout main
- Merge feature/add-homepage into main by running:
git merge feature/add-homepage
This merge succeeds cleanly. Git combines the commits from your homepage branch into main without any issues.
- Now attempt to merge feature/add-about-page by running:
git merge feature/add-about-page
Git reports a merge conflict in README.md. This is expected. Git found conflicting changes in the same part of the file and needs you to decide what to keep.
What is a merge conflict?
A merge conflict happens when two branches change the same lines of the same file. Git cannot automatically pick one version over the other, so it pauses the merge and asks you to resolve it manually.
The first merge worked because main had not touched README.md at all. The second merge conflicts because main now has a different version of README.md (from the first merge) than what the about branch expects.
First merge also failed?
Make sure you ran git checkout main before merging. If you are still on a feature branch, the merge will behave differently.
Run git branch to confirm that main is marked with an asterisk (*). If not, switch to it first.
Help me figure out why my first merge failed.
Resolve the conflict in VS Code
VS Code highlights merge conflicts with colored sections and inline buttons. You will edit the file to keep content from both branches, remove the conflict markers, and complete the merge.
- Open README.md in VS Code. You should see conflict markers that look like this:
# Team Git Workflow Demo
A project demonstrating professional Git workflow practices.
<<<<<<< HEAD
## Features
- Homepage with hero section
=======
## Features
- About page with bio
>>>>>>> feature/add-about-page
What do these markers mean?
The <<<<<<< marker starts the conflict section. Everything between it and ======= is what main currently has (from the first merge).
Everything between ======= and >>>>>>> is what the incoming branch wants to add. Your job is to combine both versions and delete all three marker lines.
- Delete all the conflict markers (<<<<<<<, =======, >>>>>>>) and combine both features into a single list.
- Your resolved README.md should look exactly like this:
# Team Git Workflow Demo
A project demonstrating professional Git workflow practices.
## Features
- Homepage with hero section
- About page with bio
What does this resolution do?
Instead of picking one version over the other, you kept both features in a single list. This is the most common resolution strategy in real teams. Both developers' work is preserved under one clean heading.
- Save README.md.
- Stage the resolved file and complete the merge by running these commands:
git add README.md
git commit -m "fix: resolve merge conflict in README features list"
- Verify the merge is complete by running:
git log --oneline
You should see the merge conflict resolution commit at the top of the log. Running git status should show a clean working tree with nothing to commit.
Still seeing conflict markers or a dirty status?
If git status still shows unmerged paths, you may have forgotten to run git add README.md before committing. Stage the file first, then run the commit command again.
If your commit fails with a message about conflict markers still present, open README.md and search for <<<<<<<. Remove any remaining markers, save, and run the add/commit again.
Help me resolve my merge conflict.
✔️ Awesome, I've got everything!
Great. Double check you have saved README.md and that git status shows a clean working tree.
ⓧ I'd like to double check the full code
Here is what your README.md should look like on the main branch after resolving the conflict:
# Team Git Workflow Demo
A project demonstrating professional Git workflow practices.
## Features
- Homepage with hero section
- About page with bio
You just resolved your first merge conflict. This is the exact scenario that trips up developers on day one of a team project. Next up, you will open your first pull request on GitHub and learn how teams review code before merging.
Open and Merge Pull Requests on GitHub
In the last step, you resolved your first merge conflict and proved you can handle one of Git's most intimidating scenarios. Now it's time to learn how professional teams actually integrate code changes.
On real teams, you never merge directly into main from your terminal. Instead, you open a pull request on GitHub so teammates can review your code before it reaches production. In this step, you will create a feature branch with a stylesheet, open a PR, and merge it using the squash merge strategy.
In this step, get ready to:
- Create a feature branch with a new stylesheet and push it to GitHub.
- Open a pull request with a conventional title and descriptive body.
- Review and merge the PR using squash and merge.
Create a new feature branch and push it
Before opening a pull request, you need something to review. You will create a stylesheet that adds base styling and color variables to the project.
- Switch to your main branch and create a new feature branch by running these commands:
git checkout main
git checkout -b feature/add-styles
What do these commands do?
The first command switches you back to main so your new branch starts from the latest code. The second creates and switches to a new branch called feature/add-styles.
- Create a new file called styles.css in your project folder. In VS Code, click the **New File** icon in the **Explorer** sidebar and name it styles.css.
- Paste the following CSS into styles.css:
:root {
--primary-color: #2d3748;
--accent-color: #4a90d9;
--background-color: #f7fafc;
--text-color: #1a202c;
}
body {
font-family: system-ui, -apple-system, sans-serif;
background-color: var(--background-color);
color: var(--text-color);
max-width: 800px;
margin: 0 auto;
padding: 2rem;
line-height: 1.6;
}
h1 {
color: var(--primary-color);
}
a {
color: var(--accent-color);
}
button {
background-color: var(--accent-color);
color: white;
border: none;
padding: 0.5rem 1rem;
cursor: pointer;
border-radius: 4px;
}
form {
display: flex;
flex-direction: column;
gap: 1rem;
max-width: 400px;
}
input, textarea {
padding: 0.5rem;
border: 1px solid var(--primary-color);
border-radius: 4px;
}
What does this stylesheet do?
The :root block defines CSS custom properties (color variables) that you can reuse throughout the stylesheet. This keeps your colors consistent and easy to change later.
The remaining rules set a clean font stack, center the page content, and style links, buttons, and form elements using those variables.
- Save styles.css.
Now you need to link this stylesheet in your existing HTML files so the browser knows to load it.
- Open index.html in VS Code.
- Find this line inside the <head> section:
<title>Team Git Workflow Demo</title>
- Add this line directly below it:
<link rel="stylesheet" href="styles.css">
- Save index.html.
- Open about.html in VS Code.
- Find this line inside the <head> section:
<title>About - Team Git Workflow Demo</title>
- Add this line directly below it:
<link rel="stylesheet" href="styles.css">
- Save about.html.
✔️ Awesome, I've got everything!
Great. Make sure all three files are saved before committing.
ⓧ I'd like to double check the full code
Here is what each file should look like at this point:
:root {
--primary-color: #2d3748;
--accent-color: #4a90d9;
--background-color: #f7fafc;
--text-color: #1a202c;
}
body {
font-family: system-ui, -apple-system, sans-serif;
background-color: var(--background-color);
color: var(--text-color);
max-width: 800px;
margin: 0 auto;
padding: 2rem;
line-height: 1.6;
}
h1 {
color: var(--primary-color);
}
a {
color: var(--accent-color);
}
button {
background-color: var(--accent-color);
color: white;
border: none;
padding: 0.5rem 1rem;
cursor: pointer;
border-radius: 4px;
}
form {
display: flex;
flex-direction: column;
gap: 1rem;
max-width: 400px;
}
input, textarea {
padding: 0.5rem;
border: 1px solid var(--primary-color);
border-radius: 4px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Team Git Workflow Demo</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<h1>Welcome to Our Project</h1>
<p>This project demonstrates professional Git workflow practices including branching, pull requests, and interactive rebase.</p>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>About - Team Git Workflow Demo</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<h1>About</h1>
<section>
<h2>Bio</h2>
<p>A developer learning professional Git workflows for team collaboration.</p>
</section>
</body>
</html>
- Stage all changes, commit, and push to GitHub by running these commands:
git add .
git commit -m "feat: add base stylesheet with color variables"
git push -u origin feature/add-styles
What do these commands do?
The git add . stages all new and modified files. The commit uses the feat: conventional commit prefix to signal a new feature. The push creates the remote branch on GitHub and sets it as the upstream tracking branch.
- Confirm the push succeeded by checking that the terminal shows a message mentioning feature/add-styles with a new remote tracking branch.
Push rejected or authentication error?
If Git asks for credentials, make sure you are signed into GitHub in your browser and have previously authenticated Git (via HTTPS credential helper or SSH key).
If the push is rejected because the remote branch already exists, run git push -u origin feature/add-styles --force to overwrite it. This is safe because you are the only contributor.
Why is my push to GitHub failing?
Open a pull request on GitHub
Your branch is now on GitHub. Time to open a pull request so you can practice the review workflow that every professional team uses.
- Go to your repository on GitHub in your browser.
- You should see a yellow banner near the top of the page with a Compare & pull request button for the feature/add-styles branch. Click it.
What if the yellow banner is not showing?
If you do not see the banner, click the Pull requests tab at the top of your repository, then click New pull request. Select feature/add-styles as the compare branch and main as the base branch.
- In the Title field, enter a conventional commit-style title:
feat: add base stylesheet with color variables
- In the description box below, write a short explanation of what the PR does, why it was made, and how to test it. For example:
## What
Adds a base stylesheet with CSS custom properties for consistent theming.
## Why
The project needs a shared set of color variables and base styles before we build out more pages.
## How to test
Open index.html or about.html in a browser and confirm the styles are applied.
Why write a PR description?
On real teams, reviewers do not have the context you have. A good description answers what changed, why it changed, and how to verify it works. This saves reviewers time and prevents misunderstandings.
- Click Create pull request to submit it.
Your pull request is now open and ready for review.
Review and merge the pull request
In a team setting, a colleague would review your PR before merging. Since you are working solo, you will simulate both sides of the review process.
- On the pull request page, click the Files changed tab.
- Review the diff showing your new styles.css file and the updated HTML files. This is what a reviewer sees when they check your code.
- Hover over any line in the diff and click the blue + icon that appears to add a review comment. Type something like "Clean set of variables" and click Add single comment.
Why practice commenting?
Code review is a two-way conversation. On a team, you will both give and receive comments on PRs. Practicing the comment flow now means you will be comfortable doing it on a real team.
- Switch back to the Conversation tab by clicking it at the top of the PR.
- Scroll to the bottom of the page where you see the merge options.
- Click the dropdown arrow next to the green Merge pull request button.
- Select Squash and merge from the dropdown menu.
- Click Squash and merge again to confirm.
- Click Confirm squash and merge.
- When GitHub offers to delete the branch, click Delete branch.
What is squash and merge?
Squash and merge combines all commits from your feature branch into a single commit on main. This keeps your main branch history clean. Instead of seeing every small work-in-progress commit, reviewers see one meaningful commit per feature.
This is the most common merge strategy on professional teams because it produces a readable, linear history.
- Confirm the merge succeeded by checking that the PR page now shows a purple Merged badge.
- Click the Code tab to return to the repository root. You should see styles.css listed in the file tree alongside your other files.
Don't see the Squash and merge option?
If the dropdown only shows Merge pull request or Rebase and merge, your repository settings may not have squash merging enabled. Go to your repository Settings tab, scroll to Pull Requests, and check the box for Allow squash merging. Then return to your PR and try again.
Why can't I see squash and merge on my pull request?
You have successfully opened, reviewed, and merged a pull request using the squash merge strategy. Next up, you will learn how to clean up messy commit history using interactive rebase before even opening a PR.
Clean Up History with Interactive Rebase
You now have a working pull request workflow. But there is one more skill that separates entry-level Git users from intermediate ones: cleaning up messy commit history before merging.
In real projects, developers often make quick "work in progress" commits while building a feature. Before opening a PR, they squash those messy commits into one clean commit using interactive rebase. In this step, you will deliberately create messy commits and then rewrite them into a single, professional commit.
In this step, get ready to:
- Create a feature branch with several messy WIP commits.
- Use interactive rebase to squash four commits into one clean commit.
- Push the cleaned branch and merge it via pull request.
Create messy commits to clean up
Before you can practice rewriting history, you need some messy history to rewrite. You will create a contact page in several quick commits, the way developers often work when iterating fast.
- Switch to your VS Code terminal and pull the latest changes from main by running these commands:
git checkout main
git pull origin main
- Create a new feature branch by running:
git checkout -b feature/add-contact
What does this command do?
This creates a new branch called feature/add-contact and switches to it in one step. You are branching from the latest main so your feature starts with all merged work.
- Create a new file called contact.html in your project folder. Add this basic structure to it:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Conact - Team Git Workflow Demo</title>
</head>
<body>
<h1>Contact</h1>
</body>
</html>
Why is there a typo?
The title says "Conact" instead of "Contact" on purpose. This simulates a real typo you would fix in a later commit. You will squash all these commits together at the end, so the typo never appears in your final history.
- Save contact.html and make your first messy commit by running:
git add contact.html
git commit -m "wip: start contact page"
- Now add a form to contact.html. Replace the entire <body> section with this:
<body>
<h1>Contact</h1>
<form>
<label for="name">Name:</label>
<input type="text" id="name" name="name">
<label for="email">Email:</label>
<input type="email" id="email" name="email">
<label for="message">Message:</label>
<textarea id="message" name="message"></textarea>
<button type="submit">Send</button>
</form>
</body>
- Save the file and commit with:
git commit -am "wip: add form"
- Now fix the typo in the <title> tag. Change Conact to Contact so it reads:
<title>Contact - Team Git Workflow Demo</title>
- Save and commit the typo fix:
git commit -am "fix typo"
- Finally, add a stylesheet link inside the <head> section, right before the closing </head> tag:
<link rel="stylesheet" href="styles.css">
- Save and commit:
git commit -am "wip: link stylesheet"
- Check your commit history by running:
git log --oneline
You should see four messy commits at the top of the log: "wip: start contact page", "wip: add form", "fix typo", and "wip: link stylesheet".
Don't see four commits?
Make sure you saved contact.html before each git commit -am command. The -a flag only stages changes to tracked files that have been saved to disk.
If the first commit worked but the rest did not, check that you used -am (not just -m) for commits 2-4. The -a flag stages modified files automatically.
help me figure out why my git commits aren't showing up
✔️ Awesome, I've got everything!
Great. Make sure you have saved contact.html after your last edit.
ⓧ I'd like to double check the full code
Here is what your contact.html should look like after all four commits:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Contact - Team Git Workflow Demo</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<h1>Contact</h1>
<form>
<label for="name">Name:</label>
<input type="text" id="name" name="name">
<label for="email">Email:</label>
<input type="email" id="email" name="email">
<label for="message">Message:</label>
<textarea id="message" name="message"></textarea>
<button type="submit">Send</button>
</form>
</body>
</html>
Use interactive rebase to squash commits
Interactive rebase lets you rewrite your branch's commit history before sharing it. You will combine all four messy commits into one clean, professional commit.
- First, make sure VS Code is set as your Git editor by running:
git config --global core.editor "code --wait"
Why do I need this command?
Interactive rebase opens a text editor for you to choose what to do with each commit. This command tells Git to open that editor in VS Code and wait for you to finish editing before continuing. Without the --wait flag, Git would not know when you are done.
- Start the interactive rebase by running:
git rebase -i HEAD~4
VS Code opens a new tab with a file listing your four commits. Each line starts with the word pick followed by a commit hash and message.
What am I looking at?
The file shows one line per commit, oldest at the top. The word at the start of each line tells Git what to do with that commit. pick means "keep this commit as-is." Changing it to squash (or just s) means "fold this commit into the one above it."
- Leave the first line as pick.
- Change the word pick to squash on the second line.
- Change pick to squash on the third line.
- Change pick to squash on the fourth line.
Your file should now look something like this (commit hashes will differ):
pick abc1234 wip: start contact page
squash def5678 wip: add form
squash ghi9012 fix typo
squash jkl3456 wip: link stylesheet
- Save and close this editor tab in VS Code (Cmd+W on macOS or Ctrl+W on Windows).
VS Code opens a second editor tab. This is where you write the final combined commit message.
- Delete all the existing text in this file.
- Type a single clean commit message:
feat: add contact page with form
- Save and close this editor tab (Cmd+W or Ctrl+W).
Your terminal shows a success message confirming the rebase completed.
Rebase opened in Vim instead of VS Code?
If you see a terminal-based editor (text with tildes ~ on empty lines), press Esc then type :q! and press Enter to exit without saving. Then run the editor config command and try the rebase again:
git config --global core.editor "code --wait"
git rebase -i HEAD~4
help me fix my Git editor so interactive rebase opens in VS Code
Seeing a rebase conflict error?
If Git reports a conflict during rebase, run git rebase --abort to cancel and start fresh. Then check that your four commits only touched contact.html and nothing else.
help me fix a conflict during interactive rebase
Push and verify the clean history
- Confirm the squash worked by running:
git log --oneline
You should see a single commit at the top: feat: add contact page with form. Your four messy commits are gone, replaced by one clean entry.
- Push the branch to GitHub by running:
git push -u origin feature/add-contact
- Open your repository on GitHub in your browser.
- Click Compare & pull request for the feature/add-contact branch.
- Write a PR title: feat: add contact page with form.
- Add a description explaining that this PR adds a contact page with a form for name, email, and message fields.
- Click Create pull request.
- On the PR page, click Merge pull request and select Squash and merge.
- Click Confirm squash and merge.
- Click Delete branch when prompted.
Why squash and merge again?
Even though you already squashed locally, selecting Squash and merge on GitHub keeps your workflow consistent. It also ensures that if any additional commits were added to the branch after the rebase, they would still be combined into one commit on main.
Don't see the Compare & pull request button?
Click the branches dropdown on your repository page and confirm feature/add-contact appears. If not, double-check your git push command completed successfully in the terminal.
help me push my feature branch and create a pull request on GitHub
You just used the #1 Git skill that separates intermediate developers from beginners. Your commit history is now clean and professional. Next up, you will put these skills to the test in the Secret Mission.
Secret mission
Rescue Work with Stash and Cherry-Pick
You accidentally started coding on main instead of a feature branch. Your changes are unsaved, uncommitted, and in the wrong place. Can you rescue them without losing a single line? Then grab a specific commit from another branch without merging everything.
Clean Up Your Resources
Clean Up Your Resources
This project runs entirely locally and uses a free GitHub repository, so there are no ongoing costs. Decide whether to keep your resources as a portfolio piece or delete them entirely.
Resources you used:
- One public GitHub repository (free, no cost).
- Local project folder on your Desktop.
Keep everything running
No action needed. Choose this if you want to keep your repository as a portfolio piece demonstrating your Git skills. The repository is free to host on GitHub indefinitely.
- Your GitHub repository stays public and accessible.
- Your local project folder remains on your Desktop.
- VS Code and Git remain installed on your machine.
Pause - I'll come back to this later
There is nothing to pause for this project. Your GitHub repository is free and does not consume resources while idle. Your local files sit on disk without using memory or CPU.
- Leave everything as-is and return whenever you are ready.
Delete - I don't want to use this again
Remove all project resources and start fresh. Follow both steps below to fully clean up.
Delete the GitHub repository:
- Go to your repository page on GitHub.
- Click Settings in the top navigation bar.
- Scroll down to the Danger Zone section and click Delete this repository.
- Click I want to delete this repository.
- Click I have read and understand these effects.
- Type your repository name in the confirmation box and click Delete this repository.
Delete the local project folder:
- Delete your project folder from the Desktop by running one of these commands in your terminal:
macOS
rm -rf ~/Desktop/team-git-workflow
Windows
Remove-Item -Recurse -Force ~\Desktop\team-git-workflow
- Replace team-git-workflow with whatever you named your project folder.
Nice Work!
Nice Work!
You just simulated a full team Git workflow from scratch. Your GitHub repository now proves you can branch, commit, resolve conflicts, rebase, and merge like an intermediate developer.
You've learned how to:
- Create and manage feature branches with conventional commits following the GitHub Flow branching strategy.
- Deliberately trigger and resolve merge conflicts, then open and merge pull requests on GitHub using squash merge.
- Use interactive rebase to squash messy commits into a clean, professional history.
- Secret Mission: Rescued misplaced work using git stash and cherry-picked specific commits across branches.
Ready to quiz yourself?