Version Control
Lesson 3 of 3
3Version Control, Git & GitHub Flow
Your first genuinely professional tool: a way to track every change to your code, and collaborate with others without anyone erasing each other's work.
What the picture shows: A change starts in your folder, git add stages it, git commit saves it as a snapshot, and git push sends it to GitHub.
Map of this part
The concepts in order, click any one to jump to it:
Two ways into the same idea
Git is like a "save" button with a memory: every save is a full snapshot of your project you can go back to. GitHub is like a shared library online where everyone puts their copy. That is how ten people work on one project without anyone erasing someone else's work.
Git is a distributed version control system: the working folder, then the staging area with git add, then the repository with git commit. GitHub hosts the remote and adds fork, pull requests and review. Good branch names and semantic versioning (semver, like 1.4.2) make collaboration and releases clear.
Before You Start
💻Terminal basics
You need to move between folders and type text commands, Git itself is a command-line tool.
The Core Idea: Git vs. GitHub
1Git, the version control tool
A program that runs locally on your machine, keeping complete "snapshots" of your project's history over time, called Commits. You can return to any past snapshot at any time.
2GitHub, the hosting & collaboration platform
A cloud service that hosts Git repositories and adds a collaboration layer on top: code review (Pull Requests), issue tracking (Issues), and test automation.
3The Staging Area
An intermediate step between editing a file and saving it into permanent history, git add puts the file in this area, and git commit turns it into a permanent snapshot.
How It Works, Step by Step: A File's Lifecycle in Git
Figure 1, every file passes through these four stages; git status tells you which stage each file is currently in.
To understand GitHub Flow in practice, you first need to understand what a "branch" actually is inside Git: a branch isn't a separate full copy of the project the way it might look from the outside, it's just a lightweight pointer to one specific commit, and it automatically moves forward every time you add a new commit on top of it. This is exactly why creating a Git branch is instant compared to copying an entire folder, git checkout -b copies nothing; it just creates a new pointer aimed at wherever main was at the moment of creation, and the two only diverge once new commits start landing on the new branch alone.
GitHub Flow builds on this by organizing team work around one stable, permanent main branch (main):
main for every new feature or fix.main stays sound at all times.main.main now contains the new feature.Step four specifically, the merge, hides an important detail: when merging, Git does one of two things depending on the two branches' history. If no new commit has landed on main since the branch was created, Git performs what's called a "fast-forward" merge, it simply moves the main pointer to point at the branch's last commit, with no new commit created at all, as if the work had happened on main itself from the start. But if main has moved forward a few steps while you worked on your branch (a teammate merged something before you), Git can't just slide the pointer, the two histories have genuinely diverged. In that case Git creates a new "merge commit" that has two parents instead of one: one is main's latest commit, the other is your branch's latest commit, this new commit is what ties the two diverging histories back together at a single point. This is exactly why you sometimes need to resolve "merge conflicts": if both branches edited the same line in two different ways, Git can't automatically decide which version is "correct," so it asks you to settle it.
Figure 2, GitHub Flow keeps main stable by isolating every feature in its own branch until it's reviewed and merged, so unvetted code never reaches it directly.
Worked Example: A Typical Workday's Commands
# Create a new branch from main git checkout -b feature/login-page # After editing files git status # Show modified files git add login.py # Move to staging area git commit -m "Add login form validation" # Permanent snapshot with a clear description # Push the branch to GitHub and open a Pull Request there git push origin feature/login-page # After the team approves and merges the PR on GitHub, update your local copy git checkout main git pull origin main
git diff already shows exactly "what" changed; your message should add the context the raw diff alone can't show.
Deep Dive: Git From the Inside and Collaboration Tools
You learned the core Git commands, and here we see what happens beneath them: how Git stores history, the difference between three working areas, why there are two different ways to undo, how conflicts arise and are resolved, and how releases are numbered.
1. History is a chain of snapshots, not of differences
Each commit is a full snapshot of the files at one moment, and it carries a pointer to the commit before it (its parent) with its author and message. A branch is not a copy of the files but a movable name pointing at a commit, and each new commit moves the name one step. That is why creating a branch is instant and cheap. HEAD is a special pointer showing which branch (or commit) you are standing on.
Figure 3, Branch then merge: the two branches share history up to B, then diverge, and the merge commit M brings them back together.
2. Three areas for every change
Any file you edit passes through three stops: the working directory (the files you see and edit), then the staging area (what you chose to put in the next snapshot), then the repository (the saved history). git add moves from the first to the second, and git commit from the second to the third. The staging area is what lets you split work into small meaningful commits even if you edited ten files.
Figure 4, A change’s journey: from the working directory to GitHub and back.
3. reset versus revert
Both go back, but with different philosophies. git reset moves the branch name back to an older commit as if what followed never happened, which suits your local work before sharing it. git revert creates a new commit that reverses the effect of an earlier one without touching history, which suits what was published and seen by others. The rule: never rewrite history that others already have.
| Aspect | git reset | git revert |
|---|---|---|
| History | Rewritten | Preserved and added to |
| Safety after sharing | Risky | Safe |
| Typical use | Cleaning local work | Undoing a published change |
4. How merge conflicts arise
Git automatically merges what each branch changed in different places. A conflict happens only when both branches edit the same lines in different ways, so Git cannot decide which is right. Then it places markers in the file separating the two versions, and your job is to decide the final content, delete the markers, then add the file and create the merge commit. A conflict is not an error but a question Git asks you.
<<<<<<< HEAD the line as it is on your branch ======= the line as it is on the branch being merged >>>>>>> feature
5. Collaboration tools in GitHub Flow
🍴Fork
A copy of someone else’s repository under your account, tied to it through two remotes: origin is your copy and upstream is the original whose updates you follow.
🌿Branch names
A name that describes the purpose such as feature/add-footer or fix/typo-readme, because the whole team reads it.
🔍Peer review
You comment on specific lines, request changes, then approve. Review catches bugs and spreads knowledge across the team.
🏷️Releases and semantic versioning
The format MAJOR.MINOR.PATCH: raise the first for a breaking change, the second for a new compatible feature, and the third for a bug fix only.
Figure 5, The complete GitHub Flow cycle from fork to release.
Write commit messages describing what the change does ("Add footer link") not what you did ("I changed stuff"). A month later you will read your own history the way strangers do.
Try it yourself
What is the difference between Git and GitHub?
Git runs on your machine and keeps snapshots (commits). GitHub hosts repositories and adds review (Pull Requests) and issues.
What does git add do?
git add moves the change to the staging area, and git commit is what turns it into a permanent snapshot.
You shipped a bug fix only, no new feature. Which part of MAJOR.MINOR.PATCH do you raise?
PATCH for a fix only, MINOR for a new compatible feature, MAJOR for a change that breaks compatibility.
Quick Review Flashcards
Check Your Understanding
If you edited a file but haven't run git add yet, and you run git commit, what happens?
Nothing is saved for that edit, commit only saves what's in the staging area, and the file stays "modified" and untracked until you add it first.
Why is opening a Pull Request preferred over pushing directly to main?
Because it allows code review before it enters the main branch, reducing the chance of introducing bugs or breaking something the rest of the team depends on.
You made a wrong commit and pushed it to GitHub where teammates saw it; which do you use and why?
revert, because it adds a commit reversing the change without rewriting history others share.
Does a conflict appear if two branches edit one file in two distant places?
No, Git merges them automatically; a conflict appears only when the same lines are edited.
Resources for this part
Sorted by kind: start with the official docs when you want the precise reference, or with an article or video when you want the explanation first.
Resources for this lesson
Grouped by type. Start with the official docs for precision, or an article or video for the explanation.
Official docs1
Articles2
Video1
Done with this lesson?
Sign in to save your progress.