Courses Learn Blog Contact
Get Started →
Lesson 10

Day 10: Git, GitHub and Project 2

Branches, pull requests, code review and merge conflicts, then the first group project: five people, one repository, a real problem and a rubric that reads the commit history.

Webbo3 Level 2: JavaScript Development 12 min read Free

Webbo3 Level 2 · JavaScript Development · Day 10 of 20

Git, GitHub and Project 2: Solve a Problem

Five people, one codebase, nobody overwriting anybody. The workflow every team you will ever join already uses.

By the end of today you can

  • Explain why teams work on branches, and never straight on main
  • Use the everyday Git commands without looking them up
  • Write commit messages that are useful when something breaks
  • Open a pull request, and review somebody else's properly
  • Resolve a merge conflict without panicking
  • Split a problem into issues and ship it as a team of five

Until today your repository has had one branch and one person. Today it gets four more people, and every habit that was merely untidy becomes genuinely expensive.

Learn this properly now, on a small project, rather than in your first job on a big one. The terminal boxes today are real: every command was run, and what you see is what Git printed. The short codes like 8e8d24f are commit ids; yours will be different, because every commit gets its own.

1. Why Branches Exist

Definition

A branch is your own line of work inside the project. You make changes on it freely, and nobody else sees them until you ask for them to be merged into the shared branch. main is the shared branch that must always work.

Real-Life Example

Five people editing one printed report with one pen, passing it around. Somebody crosses out a paragraph another person still needed, and nobody can tell who changed what.

Branches give each person a photocopy to scribble on. When their part is finished and checked, it is carefully copied into the master report.

Types of Branch in a Team

What this code doesWe want a picture of how a five-person team splits its work into branches.
branching model
1
2
3
4
5
6
7
8
main                   always working, always ready to deploy
|
+-- development        where finished features are combined and tested
    |
    +-- feature/search        Chidinma
    +-- feature/api-client    Musa
    +-- feature/filters       Amaka
    +-- fix/empty-state       Tunde
NOTE   
A plan, not a command. Each person works on their own feature branch, which is merged into development, which is merged into main when it all works together.
Picture This

Picture everyone with their own photocopy of the report. The master copy (main) is only ever changed by carefully copying in a finished, checked part.

2. The Commands You Will Use Every Day

Definition

Git records your project as a series of commits: saved snapshots, each with a message. You stage the changes you want in the next snapshot, commit them, and push them to GitHub so the team can see them.

Real-Life Example

Packing a parcel. You choose which items go in the box (git add), seal it with a label saying what is inside (git commit), and hand it to the courier (git push).

Types of Command

CommandWhat it does
git statusWhat have I changed? Run it constantly.
git switch -c nameMake a new branch and move onto it
git add fileStage a change for the next commit
git commit -m "message"Save the staged changes as a snapshot
git push -u origin nameSend a new branch to GitHub for the first time
git pullFetch and bring in everyone else's merged work
git merge nameBring another branch's work into this one
What this code doesWe want to go through a real day's Git: set up, commit, create a feature branch, commit to it and push it for the team to see.
terminal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# Set up: a project, with a stand-in for GitHub called origin
git init -q --bare origin.git
git init -q -b main project && cd project
git remote add origin ../origin.git

# First commit on main, then send it to origin
echo "# Resource Finder" > README.md
git add README.md
git commit -q -m "Add README"
git push -u origin main

# Make your own branch for your feature
git switch -c feature/search

# Write some code, then check what changed
echo "export const search = () => [];" > search.js
git status --short

# Stage it, commit it with a clear message, send the branch to origin
git add search.js
git commit -m "Add search module"
git push -u origin feature/search

# The history, one line per commit
git log --oneline
OUTPUT   TERMINAL
To ../origin.git
 * [new branch]      main -> main
branch 'main' set up to track 'origin/main'.
Switched to a new branch 'feature/search'
?? search.js
[feature/search 12d008a] Add search module
 1 file changed, 1 insertion(+)
 create mode 100644 search.js
To ../origin.git
 * [new branch]      feature/search -> feature/search
branch 'feature/search' set up to track 'origin/feature/search'.
12d008a Add search module
c9c2a4b Add README

?? in the status line means Git has never seen that file before. After the commit, the log shows both snapshots, newest first.

git switch Rather Than git checkout checkout does two unrelated jobs, which is why it confuses beginners. switch changes branch and restore discards changes. You will still see checkout everywhere, so recognise it, but write the clear ones.

The Daily Routine

What this code doesWe want to see the morning routine that keeps your branch up to date with everybody else's merged work.
terminal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Set up a team repository with a development branch
git init -q -b main project && cd project
echo "v1" > app.js && git add app.js && git commit -q -m "Start the app"
git switch -q -c development
git switch -q -c feature/search

# Meanwhile, a teammate's work is merged into development
git switch -q development
echo "export const fetchResources = () => [];" > api.js
git add api.js && git commit -q -m "Add API client"

# Your morning routine: bring development's work into your branch
git switch feature/search
git merge development

# Your branch now has the teammate's file too
ls
OUTPUT   TERMINAL
Switched to branch 'feature/search'
Updating 9aa3f61..62ac06e
Fast-forward
 api.js | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 api.js
api.js
app.js
Picture This

Picture packing a parcel: choose what goes in (add), seal it with a label (commit), hand it to the courier (push). Each morning, you also open the post from your teammates (merge development).

3. Commit Messages That Earn Their Place

Definition

A commit message says what a commit changed. You will read them when something breaks and you are hunting for the commit that caused it, so they must make sense without the code.

Real-Life Example

Labels on boxes in a store room. "Stuff" and "misc" force you to open every box. "Winter jackets, size M" tells you straight away whether this is the box you need.

Instead ofWrite
updateAdd empty state to the student list
fix bugFix page not resetting to 1 when the search changes
finalNormalise API response before rendering
asdfRemove unused sort helper
changesDebounce the search input at 300ms
The Rule That Gets You There

Finish the sentence "If applied, this commit will...". Present tense, says what changed, and never mentions how long it took.

What this code doesWe want a history where every line tells you what changed, so the log reads like a list of features and fixes.
terminal
1
2
3
4
5
6
7
8
9
git init -q -b main project && cd project

# Three commits with messages that finish "If applied, this commit will..."
echo "a" > list.js && git add list.js && git commit -q -m "Add the resource list"
echo "b" >> list.js && git commit -q -am "Add empty state to the resource list"
echo "c" >> list.js && git commit -q -am "Fix page not resetting when the search changes"

# Read the history like a changelog
git log --oneline
OUTPUT   TERMINAL
e480db7 Fix page not resetting when the search changes
1709b57 Add empty state to the resource list
fdbd6ec Add the resource list
Picture This

Picture the labelled boxes: every commit message is a label that lets a stranger find the right box without opening them all.

4. Pull Requests and Code Review

Definition

A pull request (PR) on GitHub says: here is my branch, here is what it does, please check it before it goes in. Code review is a teammate reading and running it first. It is the most effective way teams catch bugs before users do.

Real-Life Example

A newspaper article goes to an editor before it is printed. The writer explains what the piece is about; the editor reads it, asks questions, and only then does it go to print.

What this code doesWe want a pull request description that tells a reviewer what the change is, why it exists and exactly how to check it.
pull request description
1
2
3
4
5
6
7
8
9
10
11
12
13
14
## What this does
Adds a debounced search box to the resource list.

## Why
Finding a resource by scrolling through 200 of them was unusable on a phone.

## How to test it
1. Open the resources page
2. Type "flex" slowly, then quickly
3. Confirm only one search runs, and the empty state shows for "zzzz"

## Notes
Search is local because the whole list is already fetched.
If the list grows past a few hundred, this should move to the API.
NOTE   
Written on GitHub when you open the pull request. It is read by your reviewer, not by a computer.

Reviewing Somebody Else's Pull Request

  1. Pull the branch and run it. A review that only reads the code misses anything that happens on screen.
  2. Ask questions rather than issuing orders. "What happens here if items is empty?" lands very differently from "this is wrong".
  3. Say what is good. A review that is only criticism makes people defensive and slower.
  4. Check what this course has taught: user text through textContent, response.ok checked, an empty state, and code the author can explain.
Never Approve a Pull Request You Did Not Read

Approving to be polite is how broken code reaches main with two names on it. If you have not understood it, say "I have not been able to review this properly yet". That is a completely acceptable thing to say, in this course and in a job.

Picture This

Picture the editor's desk: nothing goes to print until someone other than the writer has read it and understood it.

5. Merge Conflicts

Definition

A merge conflict happens when two branches changed the same lines. Git cannot know which version is right, so it stops and asks you. It is not an error, and you have not broken anything.

Real-Life Example

Two people updated the same line of the class timetable: one moved the Monday lesson to 9am, the other to 10am. The secretary cannot guess, so she puts both on the notice board and asks you to decide.

What this code doesWe want to cause a real merge conflict, two branches changing the same line, and see exactly what Git writes into the file.
terminal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
git init -q -b main project && cd project

# Both branches start from the same line
echo "const apiUrl = 'https://api.webbo3.test';" > config.js
git add config.js && git commit -q -m "Add config"

# Amaka changes the line on her branch
git switch -c feature/filters
echo "const apiUrl = 'https://api.webbo3.test/v2';" > config.js
git commit -q -am "Use version 2 of the API"

# Meanwhile the same line changes on main
git switch main
echo "const apiUrl = 'https://resources.webbo3.test';" > config.js
git commit -q -am "Point at the resources API"

# Bring Amaka's branch in: the same line changed on both sides
git merge feature/filters

# Look at what Git wrote into the file
cat config.js
OUTPUT   TERMINAL
Switched to a new branch 'feature/filters'
Switched to branch 'main'
Auto-merging config.js
CONFLICT (content): Merge conflict in config.js
Automatic merge failed; fix conflicts and then commit the result.
<<<<<<< HEAD
const apiUrl = 'https://resources.webbo3.test';
=======
const apiUrl = 'https://api.webbo3.test/v2';
>>>>>>> feature/filters

How to Resolve It

  1. Above ======= is what is already on your branch (Git calls it HEAD). Below it is what is coming in from the other branch.
  2. Edit the file so it reads correctly: keep one version, keep the other, or write a line that satisfies both.
  3. Delete all three marker lines. A leftover <<<<<<< is a syntax error, and it is the most common way a conflict resolution goes wrong.
  4. Then git add the file and git commit.

Carrying on from the conflict above, with config.js still full of markers:

What this code doesWe want to finish a conflict properly: write the agreed version, remove the markers, and commit the merge.
terminal
1
2
3
4
5
6
7
8
9
10
11
12
cd project

# The team agreed on version 2 of the resources API: write the resolved line
echo "const apiUrl = 'https://resources.webbo3.test/v2';" > config.js

# No markers left: stage it and finish the merge
git add config.js
git commit -q -m "Merge feature/filters, using version 2 of the resources API"

# The file, and the history showing both lines of work joined
cat config.js
git log --oneline --graph
OUTPUT   TERMINAL
const apiUrl = 'https://resources.webbo3.test/v2';
*   baed7e8 Merge feature/filters, using version 2 of the resources API
|\  
| * abc1520 Use version 2 of the API
* | c20f169 Point at the resources API
|/  
* 941ee4c Add config
The Habit That Prevents Most Conflicts

Merge development into your branch every morning. Conflicts grow with how long branches drift apart: merged daily, they are small and obvious; left alone for a week, they are frightening.

Picture This

Picture the secretary pinning both timetable versions on the board with a note: "Decide, then remove this note." The conflict markers are that note, and the note must come down.

6. Project 2: The Brief

Project 2 · Groups of five · Rest of the week

Students at Webbo3 cannot find good learning resources in one place. They are scattered across YouTube, blogs, documentation and WhatsApp messages, and nobody knows which are any good. Build something that fixes that.

That is the whole brief, and it names a problem rather than a product. What you build is your team's decision, and part of what is assessed. Two teams can reasonably build different things from this.

What It Must Include

  • Data from at least one real API, fetched and rendered.
  • Search, and at least one filter or category.
  • All four states from Day 9: loading, error, empty and the list.
  • Modules, not one file: at least an API layer, a render layer and the wiring (Day 6).
  • Works at phone width.
  • A README explaining the problem, the solution and how to run it.

How the Team Works

RoleOwnsStill writes code
Product LeadWhat you are building, and what is out of scopeYes
API LeadFetching, normalising, error handlingYes
UI LeadLayout, states, responsivenessYes
QA LeadTesting every branch before it merges, keeping a bug listYes
Docs LeadREADME, the demo, the presentationYes
Everybody Writes Code. No Exceptions.

A role is an extra responsibility, not a job instead of programming. The commit history is checked at assessment, and a team member with no commits fails the project, whatever their team says about them.

The Working Rhythm

  1. Break the build into GitHub Issues, one per piece of work, each small enough for one person in half a day.
  2. Assign each issue to a person. One issue, one branch, one pull request.
  3. Nobody pushes to main or development directly. Ever.
  4. Every pull request needs one review from somebody else before it merges.
  5. A five-minute stand-up each morning: what I did, what I am doing, what is blocking me.

The Marking Rubric

CriterionMarksWhat is being judged
The problem15Did you understand it and scope it sensibly, or build the first thing you thought of
It works25Real API data, search, filter, all four states, on a phone
Code quality20Modules, naming, no dead code, no repeated blocks
Git and collaboration25Branches, real commit messages, pull requests, reviews with real comments, every member committing
Presentation15Five minutes: the problem, the demo, what broke and what you did about it
The Commit History Is Read, Not Skimmed

Twenty-five of the hundred marks are for how you worked together, and the repository is the evidence. Five commits all pushed by one person an hour before the deadline is a story the graph tells clearly, and it is marked as what it is.

Do This Now

  1. Create the repository. Add a README and a .gitignore before anything else.
  2. Create development off main. Protect both branches on GitHub if your plan allows it.
  3. Open at least eight issues and assign every one of them.
  4. Everybody creates their branch and pushes one commit today, so you find out today rather than on Thursday that somebody's Git access does not work.
  5. Agree three things in writing in the README: what you are building, what is out of scope, and who reviews whose pull requests.

Checkpoint

Q1. Why does nobody push straight to main?

main must work and be deployable at all times. Anything pushed straight to it is unreviewed and untested, and when it breaks, it breaks for the whole team at once.

Q2. You get a merge conflict. Have you broken something?

No. Two branches changed the same lines and Git is asking which is right. Edit the file, delete all three marker lines, then add and commit.

Q3. What is wrong with approving a pull request you have not read?

It puts your name on code you have not checked and removes the only barrier between a bug and main. Saying you have not reviewed it yet is always the better answer.

Q4. Why merge development into your branch every morning?

Conflicts grow with drift. Daily merges produce small, obvious conflicts; a week apart produces a merge nobody wants to do.

Tick Before You Move On

  • ☐ Repository, README and .gitignore exist before any code
  • ☐ A development branch exists, and nobody is pushing to main
  • ☐ My commit messages finish "If applied, this commit will..."
  • ☐ I resolved a merge conflict and removed every marker
  • ☐ Eight or more issues exist, all assigned
  • ☐ Every one of the five of us has pushed at least one commit today
  • ☐ Scope, out of scope and review pairs are written in the README

Quick Recap

A branch is your own line of work; main stays working at all times. status, switch, add, commit, push, pull and merge are the whole daily vocabulary. Commit messages finish "If applied, this commit will...". A pull request is where review happens, and review is where bugs are caught. A conflict is a question, not a failure: decide, delete the markers, commit. Everybody codes, and twenty-five marks are for how the repository reads.

Final Scenario

It is Wednesday. Musa's API client and Amaka's filters both changed the same config line, and her pull request shows a conflict.

Nobody panics. Amaka merges development into her branch, reads the two versions between the markers, agrees the right one with Musa in the pull request comments, writes it, deletes the markers, commits, and asks Tunde to review. By lunch it is in development, and main never broke.

That is what working in a team looks like: not that nothing goes wrong, but that the workflow makes every problem small, visible and fixable.

Next week, Day 11: storage and application state. Making your applications remember things after a refresh, and keeping every piece of state in one predictable place.

Learn this with a real instructor

Free lessons take you a long way on your own. The full programmes add live classes, assignments, Skill Points and a certificate — built for African students.