SDPT Lab 2
Lab 2: Multi-Player Git, Code Reviews, and Advanced Conflict Resolution
Introduction
In Week 1, you learned how to drive Git in "single-player mode." Today, we switch to "multi-player mode." Software engineering is a team sport. When multiple engineers edit the same codebase simultaneously, collisions are inevitable, and uninterrupted work is a myth.
By the end of this 2-hour lab, you and your partner will have:
- Configured a shared team repository with strict Branch Protection.
- Used
git stashto handle an emergency "hotfix" interruption. - Conducted an iterative Code Review (requesting and pushing fixes).
- Intentionally caused a Git Merge Conflict.
- Resolved the conflict professionally using
git rebaseand force-pushing.
Requirement: Find a partner. Decide who will be Student A (The Maintainer) and who will be Student B (The Developer).
---
Part 1: Team Setup and Branch Protection (20 Minutes)
We must first create a shared workspace and establish our "Traffic Laws."
- Student A: Log into GitLab and create a new blank project named
sdpt-lab2-collaboration. - Uncheck "Initialize repository with a README".
- On the left sidebar, go to Manage -> Members.
- Click Invite members. Search for Student B by their university email.
- Assign Student B the role of Developer and click Invite.
2. Enforce Branch Protection (Student A)
The main branch is sacred. No one should be allowed to push code directly to it.
- Student A: In the project sidebar, go to Settings -> Repository.
- Expand the Protected branches section.
- Ensure the branch is set to
main(ormaster). - Set Allowed to merge to:
Developers + Maintainers. - Set Allowed to push and merge to:
No one. - Click Protect.
3. Initialize the Baseline (Student A)
Student A will push the initial skeleton code.
mkdir sdpt-lab2-collaboration
cd sdpt-lab2-collaboration
git init
Create main.cpp:
#include <iostream>
void init_hardware() {
// TODO: Initialize communication protocol
}
int main() {
std::cout << "Sytem Booting..." << std::endl; // Notice the typo!
init_hardware();
return 0;
}
Commit and push:
git add main.cpp
git commit -m "Initial baseline code"
git remote add origin git@gitlab.com:<Student-A-Username>/sdpt-lab2-collaboration.git
git push -u origin main
4. Clone the Repository (Student B)
- Student B: Copy the SSH clone URL from GitLab.
- Clone the repository to your machine:
git clone git@gitlab.com:<Student-A-Username>/sdpt-lab2-collaboration.git
cd sdpt-lab2-collaboration
---
Part 2: The Emergency Interruption & Stash (20 Minutes)
Student B is going to start working on a feature, but Student A (acting as the manager) will interrupt them with an urgent bug fix.
1. Start Feature Work (Student B)
- Student B: Create a branch for the I2C driver.
git checkout -b feature-i2c
Open main.cpp and replace the TODO comment:
void init_hardware() {
std::cout << "Initializing I2C Bus on Port B..." << std::endl;
}
Wait! Do not commit yet!
2. The Emergency (Student A)
- Student A: "Stop what you are doing! There is a typo in the main boot message ('Sytem Booting'). We need a hotfix immediately!"
3. The Stash (Student B)
Student B cannot switch to the main branch because they have uncommitted I2C changes. They must stash them.
git stash
git checkout main
git checkout -b hotfix-typo
4. Fix the Bug (Student B)
Open main.cpp and fix the typo to say "System Booting...".
git add main.cpp
git commit -m "Fix typo in boot message"
git push -u origin hotfix-typo
- Student B: Go to GitLab, open a Merge Request for the hotfix, and assign Student A.
- Student A: Review the MR, Approve it, and click Merge.
5. Resume Work (Student B)
Student B, now that the emergency is handled, return to your feature and pop your stash.
git checkout feature-i2c
git stash pop
Your I2C code has returned! Commit and push it.
git add main.cpp
git commit -m "Add I2C hardware initialization"
git push -u origin feature-i2c
Open a Merge Request for feature-i2c.
---
Part 3: Parallel Dev & Iterative Code Review (25 Minutes)
While Student B was working, Student A was supposed to be writing the SPI driver.
1. Create the Collision (Student A)
- Student A: Make sure you are on
mainand pull the latest changes (the typo fix).
git checkout main
git pull origin main
git checkout -b feature-spi
Open main.cpp and edit the EXACT SAME LINE that Student B edited:
void init_hardware() {
std::cout << "Initializing SPI Bus on Port A..." << std::endl;
}
Commit, push, and open an MR.
git add main.cpp
git commit -m "Add SPI hardware initialization"
git push -u origin feature-spi
2. The Iterative Review
- Student A: Go to Student B's Merge Request (the I2C one).
- Do NOT approve it. We are going to request a change.
- Go to the Changes tab. Click the comment bubble next to the I2C line and write: "We need to specify the baud rate here. Please add 'at 400kHz' to the output." Click Start a review and then Submit review.
3. Implementing the Fix (Student B)
- Student B: You received a change request. Update your code locally.
void init_hardware() {
std::cout << "Initializing I2C Bus on Port B at 400kHz..." << std::endl;
}
git add main.cpp
git commit -m "Update I2C init to include baud rate per code review"
git push origin feature-i2c
- Notice that your GitLab MR automatically updates!
- Student A: Check the MR again. The requested change is there. Click Approve and Merge.
---
Part 4: The Rebase Conflict (25 Minutes)
Because Student B's MR was merged first, Student A's MR (SPI) is now broken.
1. Discovering the Conflict (Student A)
- Student A: Check your
feature-spiMerge Request on GitLab. You will see a red warning: Merge blocked: merge conflicts must be resolved.
2. Fetch and Rebase (Student A)
We will resolve this using the professional Trunk-Based standard: Rebasing.
# Download the latest state of the remote server
git fetch origin
# Replay your SPI commits on top of the newly updated main branch
git rebase origin/main
Git will stop and output: CONFLICT (content): Merge conflict in main.cpp.
3. Fix the Code (Student A)
Open main.cpp. You will see the Git markers.
void init_hardware() {
<<<<<<< HEAD
std::cout << "Initializing I2C Bus on Port B at 400kHz..." << std::endl;
=======
std::cout << "Initializing SPI Bus on Port A..." << std::endl;
>>>>>>> Add SPI hardware initialization
}
Delete the markers and combine the code so BOTH interfaces initialize:
void init_hardware() {
std::cout << "Initializing I2C Bus on Port B at 400kHz..." << std::endl;
std::cout << "Initializing SPI Bus on Port A..." << std::endl;
}
4. Continue and Force Push (Student A)
Stage the resolved file and tell the rebase to continue.
git add main.cpp
git rebase --continue
Because rebasing rewrites history, your local branch and the remote branch have diverged. A normal git push will fail. You must force it.
git push --force origin feature-spi
5. Final Approval (Student B)
- Student B: Go to Student A's MR. The conflict is gone!
- Review the code, click Approve, and click Merge.
---
Lab Deliverable
To receive full credit for this week's lab, call the professor or TA over and demonstrate:
- Your GitLab MR history showing three merged requests (Hotfix, I2C, SPI).
- Inside the I2C MR, show the comment thread where a change was requested and resolved.
- Run
git log --graph --onelineon your terminal to prove the final history includes all features without broken code.