Simulate a Team Git Workflow

Branch, merge, resolve conflicts, and open a Pull Request on GitHub.

Introduction

30 Second Summary

Every software team edits the same files at the same time. Without a system to track who changed what and when, work gets overwritten and mistakes become invisible.

In this project, you will simulate a real team workflow using Git and GitHub. You will create branches, resolve a merge conflict, and open a Pull Request, leaving you with a public repository that proves you can collaborate like a professional DevOps engineer.

What You'll Build

A public GitHub repository containing server configuration files developed across multiple feature branches, with a resolved merge conflict and a merged Pull Request visible in the commit history.

By the end of this project, you'll have:

  • A GitHub repository named devops-git-workflow with multiple branches and a clean merge history.
  • A resolved merge conflict visible in the commit history, demonstrating the same process DevOps teams use daily.
  • A merged Pull Request on GitHub with a descriptive title and body, proving you can collaborate through code review.
  • Secret Mission: use git revert to safely undo a bad commit on main without rewriting history.

Are there any prerequisites?

None. This project walks you through installing and configuring every tool you need, including Git and a free GitHub account. No prior Git experience is required.

Set Up Your Repository

Every Git project starts with a repository. A repository is a folder where Git watches and records every change you make to your files.

In this step, you'll create your project folder, initialize it as a Git repository, and make your very first commit. This gives you a clean starting point for building feature branches later.

In this step, get ready to:
  • Create the devops-git-workflow project folder.
  • Initialize a Git repository.
  • Make your first commit with a README file.
Create your project folder and initialize the repository

Git needs a dedicated folder to work in. You'll create one on your Desktop so it's easy to find later.

  • Move to your Desktop by running this command:
cd ~/Desktop
  • Create your project folder, move into it, and initialize a Git repository by running these commands:
mkdir devops-git-workflow
cd devops-git-workflow
git init

What do these commands do?

  • mkdir devops-git-workflow creates a new folder with your project name.
  • cd devops-git-workflow moves your terminal into that new folder.
  • git init creates a hidden .git folder inside your project. This is where Git stores all its tracking data.
  • Confirm it worked by running:
git status

You should see "On branch main" and "No commits yet" in the output.

Seeing 'master' instead of 'main'?

This means the init.defaultBranch setting from the previous step didn't take effect. Run this to rename your branch:

git branch -m master main

Help me fix my default branch configuration

Create your first commit with a README file

A commit is a snapshot of your project at a specific point in time. Your first commit establishes the starting point that all future branches will grow from.

  • Create a README.md file, stage it, and commit it by running these commands:
echo # DevOps Git Workflow > README.md
git add README.md
git commit -m "chore: initialize repository with README"

What do these commands do?

  • echo # DevOps Git Workflow > README.md creates a new file called README.md with a heading inside it.
  • git add README.md tells Git to include this file in the next snapshot. This is called "staging."
  • git commit -m "..." saves the snapshot with a descriptive message. The chore: prefix is a conventional commit style that teams use to categorize changes.

What is conventional commit style?

Conventional commits use a prefix like feat:, docs:, or chore: to categorize each commit at a glance. DevOps teams rely on this pattern to quickly scan history and understand what changed.

Interviewers look for meaningful commit messages as a sign of professional workflow habits.

Getting a blank file on Windows PowerShell?

PowerShell treats # as a comment character. If your README.md is empty, create it manually instead. Open the VS Code Explorer sidebar, create a new file called README.md, and type this as the first line:

# DevOps Git Workflow

Save the file, then run the git add and git commit commands from above.

Help me create my README.md file

  • Verify your commit exists by running:
git log --oneline

You should see one line with a short hash followed by the message "chore: initialize repository with README".

Seeing 'error: pathspec' or no commit?

  • Make sure the filename is exactly README.md with that exact capitalization. Git is case-sensitive.
  • Double check you're inside the devops-git-workflow folder by running pwd (macOS/Linux) or Get-Location (Windows PowerShell).

Help me troubleshoot my first Git commit

✔️ Awesome, I've got everything!

Great. Double check you've saved your file and your terminal shows the commit in git log --oneline.

ⓧ I'd like to double check the full code

Here is what your README.md file should contain:

# DevOps Git Workflow

Your repository is initialized with a clean first commit. Next up, you'll create feature branches and start developing server configuration files in isolation.

Create Feature Branches and Develop in Isolation

Your repository is set up and Git knows who you are. Now it's time to build features the way real DevOps teams do.

In professional teams, developers never edit code directly on the main branch. Instead, each person creates a separate branch for the feature they're working on. This keeps everyone's work isolated until it's ready to be combined.

In this step, get ready to:
  • Create a feature branch and build an nginx configuration file on it.
  • Create a second feature branch and build an application config file on it.
  • Visualize how branches diverge from each other using a graph command.
Create and work on the nginx configuration branch

A feature branch is a copy of your project where you can make changes without affecting main. You'll create one now for an Nginx server configuration.

  • Create a new branch called feature/nginx-config and switch to it by running this command:
git checkout -b feature/nginx-config

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 checkout only switches to an existing branch.

  • Confirm you're on the new branch. You should see Switched to a new branch 'feature/nginx-config' in the terminal output.
  • In VS Code's Explorer sidebar, hover over the devops-git-workflow folder name and click the New File icon (a page with a plus sign).
  • Name the file nginx.conf and press Enter.
  • Paste the following content into nginx.conf:
server {
    listen 80;
    server_name app.example.com;

    location / {
        proxy_pass http://localhost:3000;
    }
}

What does this config do?

This is a reverse proxy configuration. It tells Nginx to listen on port 80 and forward all incoming traffic to your application running on localhost:3000.

DevOps teams use config files like this to route web traffic to the correct backend service.

  • Save nginx.conf with Ctrl+S (Windows) or Cmd+S (macOS).
  • You should see nginx.conf listed under your devops-git-workflow folder in the Explorer sidebar.

Don't see nginx.conf in the Explorer?

Make sure you clicked the New File icon on the devops-git-workflow folder itself, not a subfolder. If the file ended up in the wrong place, right-click it in the Explorer and select Delete, then create it again.

Help me find where my file was created.

✔️ Awesome, I've got everything!

Great. Make sure you've saved nginx.conf before moving on.

ⓧ I'd like to double check the full code

server {
    listen 80;
    server_name app.example.com;

    location / {
        proxy_pass http://localhost:3000;
    }
}
  • Stage and commit your new file by running these commands:
git add nginx.conf
git commit -m "feat: add nginx reverse proxy configuration"

What do staging and committing do?

git add moves a file into the staging area, which is like a loading dock for your next commit. git commit takes a snapshot of everything in the staging area and saves it permanently in your project history.

The feat: prefix is a conventional commit style that labels the type of change. Teams use these prefixes to quickly scan what each commit does.

  • Verify your commit by running:
git log --oneline
  • You should see two commits: feat: add nginx reverse proxy configuration (at the top) and chore: initialize repository with README (below it).
  • Confirm your branch by running:
git branch
  • You should see feature/nginx-config marked with an asterisk (*), showing it's your current branch.

Seeing 'nothing to commit'?

This means Git doesn't see any new or changed files. Make sure you saved nginx.conf (check for the dot on the file tab in VS Code, which indicates unsaved changes). After saving, run git add nginx.conf again.

Help me figure out why my commit failed.

Switch back to main and create a second feature branch

Now you'll see branch isolation in action. When you switch back to main, the nginx.conf file will disappear because it only exists on the feature/nginx-config branch.

  • Switch back to main and create a new branch called feature/app-config by running these commands:
git checkout main
git checkout -b feature/app-config

Why switch to main first?

Each feature branch should start from main, not from another feature branch. This keeps your branches independent so they can be merged separately.

This pattern is the core of GitHub Flow: short-lived feature branches that branch off main and merge back into main when ready.

  • In VS Code's Explorer sidebar, hover over the devops-git-workflow folder name and click the New File icon.
  • Name the file app-config.yaml and press Enter.
  • Paste the following content into app-config.yaml:
app:
  name: devops-demo
  port: 3000
  environment: development
  database:
    host: localhost
    port: 5432

What does this config do?

This YAML file defines application settings like the app name, which port it runs on, and how to connect to a database. DevOps teams store these settings in config files rather than hardcoding them, which makes it easy to change values per environment.

  • Save app-config.yaml with Ctrl+S (Windows) or Cmd+S (macOS).
  • You should see app-config.yaml listed in the Explorer sidebar.

Don't see app-config.yaml?

Check that you saved the file (look for the dot on the tab). If you accidentally named it wrong, right-click the file in the Explorer and select Rename to fix it.

Help me create my config file in the right place.

✔️ Awesome, I've got everything!

Great. Make sure you've saved app-config.yaml before moving on.

ⓧ I'd like to double check the full code

app:
  name: devops-demo
  port: 3000
  environment: development
  database:
    host: localhost
    port: 5432
  • Stage and commit your new file by running these commands:
git add app-config.yaml
git commit -m "feat: add application configuration file"
  • Verify your commit by running:
git log --oneline
  • You should see two commits: the new feat: add application configuration file commit and the original chore: initialize repository with README commit.
  • Now confirm that nginx.conf does NOT exist on this branch by running:
dir
  • If you're using Git Bash instead of PowerShell, run ls instead.
  • You should see README.md and app-config.yaml listed, but NOT nginx.conf. This proves each branch is isolated.

Still seeing nginx.conf?

Make sure you ran git checkout main before creating the feature/app-config branch. If you branched from feature/nginx-config by accident, you can fix this by switching to main and re-creating the branch:

git checkout main
git branch -D feature/app-config
git checkout -b feature/app-config

Then re-create app-config.yaml and commit it again.

Help me fix my branch structure.

Visualize the branch structure

Git can draw a text-based graph of your branch structure. This helps you see how branches diverge from each other.

  • View the branch graph by running this command:
git log --oneline --graph --all

What should I see?

You should see a forking graph showing main, feature/nginx-config, and feature/app-config diverging from the initial commit. The asterisks (*) represent commits, and the lines show how branches split apart.

This is the same kind of graph that tools like GitHub show in their branch visualizers. It proves your two feature branches are independent from each other.

Your branches are ready and each one holds its own changes in isolation. Next up, you'll merge them back together and handle your first merge conflict.

Merge Branches and Resolve a Conflict

You have two feature branches with independent work. In a real DevOps team, these branches eventually need to come back together on the main branch. This is where merging comes in.

Merging is straightforward when changes don't overlap. But when two branches edit the same file, Git can't decide which version to keep. That's called a merge conflict. In this step, you'll experience both scenarios firsthand.

In this step, get ready to:
  • Merge the nginx configuration branch into main.
  • Create a deliberate merge conflict between two branches.
  • Resolve the conflict manually and complete the merge.
Merge the nginx branch cleanly into main

Your nginx configuration lives on its own branch. Time to bring it into main so it becomes part of the official project.

  • Switch to the main branch and merge feature/nginx-config by running these commands:
git checkout main
git merge feature/nginx-config

What does this do?

git checkout main switches your working directory back to the main branch.

git merge feature/nginx-config brings all the commits from the nginx branch into main. Since main hasn't received any new commits since the branch was created, Git performs a fast-forward merge. It simply moves the main pointer forward to the latest commit on feature/nginx-config.

  • Confirm the merge worked by running:
ls

You should see both README.md and nginx.conf listed. The merge output also shows Fast-forward confirming no merge commit was needed.

Don't see nginx.conf?

Make sure you ran git checkout main before the merge. If you merged while on another branch, the file went to the wrong place.

Run git branch to confirm you're on main (marked with an asterisk).

help me fix my git merge

Create a deliberate conflict

Merge conflicts happen when two branches change the same lines in the same file. You're going to intentionally cause one so you can practice resolving it.

  • Open README.md in VS Code by clicking on it in the Explorer sidebar.
  • Replace all the content in the file with the following:
# DevOps Git Workflow

## Overview
This project demonstrates Git branching workflows for DevOps teams.

What are we setting up?

You're editing README.md on the main branch to add an Overview section. In a moment, you'll switch to the other branch and add a different section to the same file. When Git tries to merge both changes, it won't know which version to keep.

  • Save README.md with Ctrl+S.
  • Stage and commit this change by running:
git add README.md
git commit -m "docs: add project overview to README"
  • Now switch to the feature/app-config branch by running:
git checkout feature/app-config

Notice that README.md reverts to its original content. Each branch has its own version of the file.

  • Open README.md again in VS Code and replace all the content with:
# DevOps Git Workflow

## Configuration
Server configuration files for the devops-demo application.
  • Save README.md with Ctrl+S.
  • Stage and commit this change by running:
git add README.md
git commit -m "docs: add configuration description to README"
  • Switch back to main and attempt the merge by running:
git checkout main
git merge feature/app-config

Git reports CONFLICT (content): Merge conflict in README.md and Automatic merge failed; fix conflicts and then commit the result.. This is exactly what you wanted to happen.

Don't see the conflict message?

If the merge completed without a conflict, it means the README.md edits didn't overlap. Double-check that both branches modified lines below the # DevOps Git Workflow heading.

help me understand why my git merge didn't produce a conflict

Resolve the merge conflict

A merge conflict looks scary at first, but it's just Git asking you to decide what the final version should look like. You'll combine content from both branches.

  • Open README.md in VS Code. You'll see conflict markers that look like this:
<<<<<<< HEAD
## Overview
This project demonstrates Git branching workflows for DevOps teams.
=======
## Configuration
Server configuration files for the devops-demo application.
>>>>>>> feature/app-config

What do the conflict markers mean?

Everything between <<<<<<< HEAD and ======= is what main has. Everything between ======= and >>>>>>> feature/app-config is what the incoming branch has.

Your job is to delete the markers and keep whatever content you want. In a real team, you'd discuss with your teammates which version to keep. Here, you'll keep both sections.

  • Delete all the conflict markers (<<<<<<<, =======, and >>>>>>> lines) and edit the file so it contains both sections:
# DevOps Git Workflow

## Overview
This project demonstrates Git branching workflows for DevOps teams.

## Configuration
Server configuration files for the devops-demo application.
  • Save README.md with Ctrl+S.
  • Complete the merge by staging the resolved file and committing:
git add README.md
git commit -m "merge: resolve conflict combining overview and config docs"
  • Verify the merge history by running:
git log --oneline --graph

You should see a forking and merging graph with your merge commit at the top, connecting both branches back together. No conflict markers remain in README.md.

Still seeing conflict markers?

If git commit fails, open README.md and search for <<<<<<<. All marker lines must be deleted before Git accepts the commit.

Make sure you saved the file after editing. Unsaved changes in VS Code won't be picked up by git add.

help me resolve this merge conflict in README.md

✔️ Awesome, I've got everything!

Great. Double-check that you've saved README.md and that your git log --oneline --graph output shows the merge commit.

ⓧ I'd like to double check the full code

Here's what README.md should look like after resolving the conflict:

# DevOps Git Workflow

## Overview
This project demonstrates Git branching workflows for DevOps teams.

## Configuration
Server configuration files for the devops-demo application.

You just resolved a real merge conflict using the same process DevOps teams use daily. Next up, you'll push everything to GitHub and create a Pull Request to see how team collaboration works in practice.

Push to GitHub and Create a Pull Request

You have a complete branching history on your local machine, including a resolved merge conflict. The next challenge is getting this work onto GitHub where teammates (and interviewers) can see it.

In this step, you will push your repository to GitHub, create a new feature branch, and open a Pull Request to propose and merge changes. This is exactly how DevOps teams collaborate on shared codebases.

In this step, get ready to:
  • Create a public GitHub repository and push your local work.
  • Create a new feature branch and push it to GitHub.
  • Open and merge a Pull Request on GitHub.
Create a repository on GitHub and push

Your local repository needs a remote home on GitHub. You will create an empty repository on GitHub and connect it to your local project.

  • Open your browser and go to github.com.
  • Click the + button in the upper-right corner.
  • Select New repository.
  • Enter devops-git-workflow in the Repository name field.
  • Enter Git branching workflow demonstration for DevOps in the Description field.
  • Select Public for the visibility.
  • Leave all initialization options unchecked (you already have a local repository with a README).
  • Click Create repository.

Why not initialize with a README?

GitHub offers to create a README, .gitignore, and license when you create a repository. Since you already have commits locally, initializing on GitHub would create a conflicting history. Starting with an empty remote lets you push your existing work cleanly.

GitHub shows a page with setup instructions. You will use the commands for pushing an existing repository.

  • Switch back to your VS Code terminal and connect your local repository to GitHub by running these commands:
git remote add origin https://github.com/[[GITHUB_USERNAME="your GitHub username"]]/devops-git-workflow.git
git push -u origin main

What do these commands do?

  • git remote add origin tells Git where your remote repository lives. The name origin is the conventional name for your primary remote.
  • git push -u origin main uploads all your local commits to GitHub. The -u flag sets up tracking so future pushes only need git push.

What about authentication?

When you push for the first time, Git needs to verify your identity with GitHub. You may see a browser window open asking you to sign in, or Git may prompt you for credentials in the terminal.

If prompted for a password in the terminal, enter a Personal Access Token (not your GitHub password). GitHub no longer accepts password-based authentication for Git operations.

  • Refresh your repository page on github.com.

You should see your repository with README.md, nginx.conf, and app-config.yaml listed.

Push failed or permission denied?

  • Double-check that the repository name in your remote URL matches devops-git-workflow exactly.
  • Make sure you are signed in to the correct GitHub account in your browser.
  • If Git asks for a password, use a Personal Access Token from your GitHub account settings, not your login password.

Help me troubleshoot my git push to GitHub

Create a new feature branch and push it to GitHub

In a real team, you would never commit new features directly to main. You will create a new branch for a monitoring configuration, commit it, and push the branch to GitHub.

  • Create a feature branch for the monitoring config by running this command:
git checkout -b feature/monitoring

Now you will create the monitoring configuration file.

  • Create a new file named monitoring.yaml in your devops-git-workflow folder. In VS Code, click the New File icon in the Explorer sidebar, type monitoring.yaml, and press Enter.
  • Add the following content to monitoring.yaml:
monitoring:
  enabled: true
  endpoint: /health
  interval_seconds: 30
  alerts:
    - type: cpu_usage
      threshold: 80
    - type: memory_usage
      threshold: 90

What does this configuration do?

  • endpoint: /health defines a URL path that monitoring tools can ping to check if the app is alive.
  • interval_seconds: 30 means the health check runs every 30 seconds.
  • The alerts section triggers notifications when CPU exceeds 80% or memory exceeds 90%.
  • Save monitoring.yaml.
  • Stage, commit, and push the branch to GitHub by running these commands:
git add monitoring.yaml
git commit -m "feat: add health monitoring configuration"
git push -u origin feature/monitoring

What does pushing a branch do?

The git push -u origin feature/monitoring command creates a copy of your branch on GitHub. This makes the branch visible to teammates and allows you to open a Pull Request from it.

  • Go to your repository page on GitHub and refresh it.

You should see a yellow banner saying the feature/monitoring branch had recent pushes, with a Compare & pull request button.

Don't see the yellow banner?

  • Make sure the push completed without errors in your terminal.
  • Try refreshing the GitHub page. The banner appears on the repository's main page, not on the Code tab of a specific branch.

Help me find the Compare & pull request button on GitHub

Create and merge the Pull Request on GitHub

A Pull Request is how you propose merging your branch into main. It gives teammates a chance to review your changes before they become part of the shared codebase.

  • Click Compare & pull request in the yellow banner on GitHub.
  • Enter feat: add health monitoring configuration as the title.
  • Enter Adds monitoring.yaml with health check endpoint and alert thresholds for CPU and memory usage. in the description body.
  • Click Create pull request.

Why write a descriptive PR body?

In a team, Pull Request descriptions help reviewers understand your changes without reading every line of code. A good description names what was added and why. This is a skill interviewers look for in DevOps candidates.

GitHub shows you the Pull Request page with the diff of your changes. Since you are both the author and reviewer on this repository, you can merge it yourself.

  • Review the diff showing your monitoring.yaml changes.
  • Click Merge pull request at the bottom of the Pull Request.
  • Click Confirm merge.
  • Click Delete branch to clean up the remote branch.

Why delete the branch?

Once a feature branch is merged, it has served its purpose. Deleting it keeps your repository tidy and signals to teammates that the work is complete. The commit history preserves all the changes.

Your Pull Request is now merged on GitHub. The last step is to sync your local repository with the remote.

  • Switch back to VS Code terminal and sync your local main by running these commands:
git checkout main
git pull origin main

What does git pull do here?

The merge happened on GitHub's servers, so your local main branch is behind. The git pull origin main command downloads the merge commit and updates your local branch to match.

  • Verify the sync worked by running:
git log --oneline

You should see the PR merge commit at the top of the log. The file monitoring.yaml now exists locally on main.

Don't see monitoring.yaml locally?

  • Make sure you ran git checkout main before pulling. If you are still on feature/monitoring, the pull targets the wrong branch.
  • Run git branch to confirm you are on main (indicated by the asterisk).

Help me sync my local main branch after merging a PR on GitHub

✔️ Awesome, I've got everything!

Great. Double check you have saved all files and your local main is synced with GitHub.

ⓧ I'd like to double check the full code

Here is the full content of monitoring.yaml (the new file created in this step):

monitoring:
  enabled: true
  endpoint: /health
  interval_seconds: 30
  alerts:
    - type: cpu_usage
      threshold: 80
    - type: memory_usage
      threshold: 90

Your other files (README.md, nginx.conf, app-config.yaml) remain unchanged from the previous step.

Secret mission

Safely Undo a Bad Commit with git revert

You just merged a PR like a pro. But what happens when someone pushes a bad commit to main? In this mission, you will learn the safe way to undo mistakes on shared branches without rewriting history.

Clean Up Your Resources

Clean Up Your Resources

This project runs entirely locally with a free GitHub repository, so there are no ongoing costs. Decide whether to keep your resources for your portfolio, pause them, or delete them entirely.

Resources you used:

  • Local project folder devops-git-workflow on your Desktop.
  • GitHub repository devops-git-workflow (public).

Keep everything running

No action needed. Choose this if you want to keep the repository on your GitHub profile as a demonstration of your Git workflow skills.

  • Your local devops-git-workflow folder stays on your Desktop.
  • Your GitHub repository remains public and visible to recruiters or interviewers.
  • Git is still installed on your machine for future projects.

Pause - I'll come back to this later

There are no running processes to stop. Your local files and GitHub repository are already in a paused state by default.

  • Your local folder and GitHub repository stay as they are until you return.
  • No costs accumulate while you are away.

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 local project folder:

  • In your VS Code terminal, navigate up one level and remove the folder by running:
cd ~/Desktop
rm -rf devops-git-workflow

On Windows PowerShell?

Use this command instead:

cd ~/Desktop
Remove-Item -Recurse -Force devops-git-workflow

Delete the GitHub repository:

  • On GitHub, navigate to your devops-git-workflow repository.
  • Click Settings under the repository name.
  • 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 devops-git-workflow to confirm, then click Delete this repository.

Nice Work!

Nice Work!

You just built a complete DevOps team workflow from scratch using Git and GitHub. Your repository now demonstrates the exact branching, merging, and collaboration skills that DevOps internship interviewers test for.

You've learned how to:

  • Built a repository with a professional branching structure showing feature branches merging into main.
  • Resolved a real merge conflict by combining changes from two branches.
  • Created and merged a Pull Request on GitHub with a descriptive title and body.
  • Secret Mission: Safely reverted a bad commit using git revert without rewriting shared history.

Ready to quiz yourself?