Git records versions on your computer. GitHub stores and shares a Git repository online.
A commit resembles a game save point; a branch is a separate path where you can try a change.
edit → commit → push → review → merge
Series: Playwright Zero to Expert | Demo app used throughout this series: saucedemo.com
Picture this, without version control: you’re working on a Playwright test suite, and you make a change that breaks twelve tests. You don’t remember exactly what you changed, or when, or whether a teammate’s changes from yesterday got mixed in with yours. Your only backup is a folder named tests-final-v3-actually-final. This isn’t a hypothetical — it’s genuinely how software was managed before version control became standard, and it’s exactly the mess Git exists to prevent.
Version Control, Properly Explained
Version control
is a system that tracks every change made to a set of files over time — who changed what, when, and why — while letting you go back to any previous point whenever you need to, and letting multiple people work on the same codebase simultaneously without overwriting each other’s work by accident. Git is, by a wide margin, the most widely used version control system in the software industry today, and it’s what nearly every real Playwright framework you’ll ever work on will be managed with.
A repository (often shortened to “repo”) is a project folder that Git is actively tracking — every change inside it, from this point forward, can be recorded, inspected, and reverted.
Here’s the mental model worth holding onto: Git doesn’t just keep one single “current” copy of your project. It keeps a complete, navigable history of every meaningful change ever made — like a very detailed, permanent save-file system for your code, where you can jump back to any earlier save point at will, compare any two save points to see exactly what changed between them, and even have multiple independent “storylines” of the project running in parallel (that’s what a branch is, covered shortly) before deciding which one becomes the real, official version.
Analogy: The Multi-Author Book Project Imagine you and a group of co-authors are writing a complex novel together:
- Working Directory (Your Desk): You are writing draft paragraphs on a notepad. You can scratch things out and rewrite them; this is your local workspace.
- Staging Area (The Review Folder): Once you’ve polished a page, you place a photocopy of it in a shared review folder on your desk. You haven’t sent it to the publisher yet, but you’ve selected it to be part of the next chapter print.
- Local Repository (The Chapter Bind): Once you gather a complete set of pages from the folder, you bind them into a chapter draft, stick a post-it note on it detailing what was written (“Draft Chapter 3: Added Prologue”), and save it in your cabinet (a Commit).
- Remote Repository (The Publisher’s Vault): You upload a copy of your chapters to a shared online cloud vault (GitHub) so all co-authors can read your progress and compile their sections together.
📊 Visual Flowchart: The Git Lifecycle
Here is how changes move through Git’s tracking stages:
graph LR
WD["Working Directory<br>(Unstaged edits in files)"] -- "git add" --> SA["Staging Area<br>(Staged changes in index)"]
SA -- "git commit" --> LR["Local Repository<br>(Recorded as commits in HEAD)"]
LR -- "git push" --> RR["Remote Repository<br>(Shared on GitHub)"]
RR -- "git pull" --> WD
Commits — the Core Unit of Git
A commit is a saved snapshot of your project at a specific point in time, along with a short message describing what changed and why.
Think of writing tests without commits as writing a long research paper with no save points at all — one continuous, unbroken block of work, with no way to see how your thinking evolved, and no way to safely undo just the last change if it turns out to be wrong.
Committing regularly, with clear, honest messages, turns your project’s history into something genuinely useful — a readable, and reversible, record of how the test suite actually grew and changed over time.
git add login.spec.ts
git commit -m "Add login test for standard user"
git add stages a file — tells Git “include this file’s current changes in the next commit I make.” git commit -m "..." actually creates the commit, permanently recording that snapshot in the project’s history, with the message explaining what it does.
A genuinely common beginner habit worth correcting early: writing one enormous commit at the very end of a day’s work, with a vague message like "updates" or "fixes". This technically works, but it throws away almost all the real value commits provide — if something in that giant block of changes breaks a test three weeks later, a message like "updates" tells you nothing about where to even start looking.
Small, frequent, clearly-described commits ("Add login test for locked-out user", "Fix flaky wait in checkout test") create a history that’s actually useful to read later, by you or by a teammate.
Branches
A branch is an independent line of development — a way to work on something new (a new test, an experiment, a fix) without touching the main, stable version of the project until you’re genuinely ready to merge it in.
git branch add-checkout-tests # create a new branch
git checkout add-checkout-tests # switch to it
Or, as a single combined command:
git checkout -b add-checkout-tests
Picture the project’s history as a timeline that can literally split and later rejoin:
main: A ── B ── C ─────────────────── F (merged)
\ /
add-checkout-tests: D ── E ───────────
While you’re working on the add-checkout-tests branch, the main branch stays completely untouched and stable — anyone else on the team can keep working from main without being affected by your in-progress, possibly broken, work-in-progress checkout tests. Once your new tests are genuinely done and working, you merge the branch back into main, folding your changes into the shared, official history.
git checkout main
git merge add-checkout-tests
This branching model is exactly why real teams can have many people working on the same Playwright test suite simultaneously — one person adding checkout tests, another fixing a flaky login test, another building out a new page object — all without stepping on each other’s work, until each piece is ready to be folded into the shared main branch deliberately.
GitHub, and Remote Repositories
Everything covered so far — commits, branches, merges — happens locally, on your own machine. GitHub (and similar platforms like GitLab or Bitbucket) is a service that hosts a remote copy of your Git repository, on the internet, so it can be shared, backed up, and collaborated on by a whole team, not just you, on your one machine.
git clone https://github.com/your-team/playwright-tests.git
git clone
downloads a complete copy of a remote repository — including its entire history, not just its current files — onto your machine, ready to work with locally.
git status
git status
shows you the current state of your working folder — which files you’ve changed, which are staged and ready to be committed, which aren’t tracked by Git at all yet. This is one of the commands you’ll genuinely run constantly, almost as a reflex, to stay oriented on exactly what you’ve changed before committing it.
git pull
git pull
fetches the latest changes from the remote repository (GitHub) and merges them into your current local branch — essential for staying up to date with whatever your teammates have already pushed, before you start layering more changes on top.
git push
git push
sends your local commits up to the remote repository, making them visible and available to everyone else on the team.
Putting the core commands together into a realistic day-to-day flow:
git pull (get the latest changes from the team)
git checkout -b add-checkout-tests (start a new branch for your work)
... write and edit test files ...
git add checkout.spec.ts
git commit -m "Add checkout flow test for standard user"
git push (send your branch up to GitHub)
... open a Pull Request on GitHub for review ...
git checkout main
git pull (get everyone else's latest work, including your merged changes)
That Pull Request step deserves a proper mention here, even though we’re keeping the deep dive on code review culture for Part 39 — a Pull Request (PR) is a request, made through GitHub, to merge your branch’s changes into main, which typically triggers a teammate (or several) reviewing your actual code changes before they’re allowed in.
For test code specifically, this matters just as much as it does for application code: a badly written test — one with a brittle locator, or a hardcoded wait, or unclear intent — can quietly poison a shared test suite for months if nobody reviews it before it merges.
.gitignore
Recall from Part 4 that node_modules should never be committed to Git, since it can always be perfectly regenerated from package.json and package-lock.json. A .gitignore file is how you tell Git, explicitly, “never track these files or folders, even if they exist in this project.”
A typical .gitignore for a Playwright project looks roughly like this:
node_modules/
test-results/
playwright-report/
.env
Each line here exists for a genuine, specific reason:
node_modules/— regenerable frompackage.json/package-lock.json, as covered in Part 4; committing it is pure wasted space.test-results/andplaywright-report/— these are generated fresh every time you run your tests (screenshots, videos, traces, HTML reports, covered properly in Part 23 and Part 34) — they’re output, not source code, and committing them would mean your repository’s history fills up with constantly-changing binary files from every single test run..env— this is the important one to genuinely understand, not just copy:.envfiles typically hold secrets — API keys, passwords, environment-specific configuration (Part 16 covers this properly). Committing a.envfile means permanently baking real credentials into your project’s history, visible to anyone with access to the repository, forever — even if you delete the file in a later commit, it still exists in the project’s history. This is a genuinely serious, common real-world mistake, and.gitignore-ing.envfrom the very first commit of a project is the correct, simple prevention.
How It Works in a Real Test Run
A production test change normally travels through working files, a focused commit, a pushed branch, a pull request, automated CI checks, review, and merge. Git records file history; GitHub coordinates collaboration around that history.
Commit the test source and stable configuration, but ignore generated reports, videos, traces, browser binaries, node_modules, and secrets unless the repository has a deliberate reason to version a particular artifact.
Interview Questions
Q: What is the difference between Git and GitHub?
Ans: Git is the actual version control system — the tool that tracks changes, commits, and branches, running locally on your machine. GitHub is a separate service that hosts remote copies of Git repositories on the internet, enabling sharing, backup, and collaboration across a team. You can use Git entirely locally without ever touching GitHub; GitHub simply gives Git repositories a shared, online home.
Q: What is a commit, and why is it considered bad practice to make one enormous commit at the end of a day with a vague message?
Ans: A commit is a saved snapshot of the project at a specific point in time, with a message describing what changed and why. A single enormous, vaguely-described commit throws away most of the real value commits provide — if something in that large block of changes turns out to be broken later, a message like “updates” gives you no useful starting point for figuring out which specific change caused it. Small, frequent, clearly-described commits create a project history that’s actually useful to read and reason about later.
Q: What is a branch, and why does it matter for a team working on the same test suite?
Ans: A branch is an independent line of development, letting you work on something new — a test, a fix, an experiment — without affecting the main, stable version of the project until you’re ready to merge it in. This matters for a team because multiple people can work on entirely different parts of the same test suite simultaneously, each on their own branch, without their in-progress, possibly broken work interfering with each other or with the shared main branch.
Q: What is the difference between git pull and git push?
Ans: git pull fetches the latest changes from the remote repository (like GitHub) and merges them into your current local branch, bringing your local copy up to date with what the team has already shared. git push does the reverse — it sends your own local commits up to the remote repository, making them visible and available to the rest of the team.
Q: Why should node_modules be excluded from Git, but source test files shouldn’t be?
Ans: node_modules contains entirely derived, regenerable code — it can be recreated exactly from package.json and package-lock.json by running npm install, so committing it would just be wasted space and unnecessary noise in the project’s history. Source test files, by contrast, are the actual, original work that can’t be regenerated from anything else — they’re precisely what version control exists to track and protect.
Q: A .env file containing real API credentials was accidentally committed to a Git repository, then deleted in a later commit. Is the secret actually safe now? Why or why not?
Ans: No — deleting a file in a later commit does not remove it from the repository’s history. The credentials still exist in the earlier commit, and anyone with access to the repository (or its full history) can still retrieve them. The correct approach is to have .gitignored the .env file from the very first commit, before it was ever tracked, and if credentials were genuinely exposed, to treat them as compromised and rotate (replace) them entirely, rather than relying on deletion alone.
Q: What is a Pull Request, and why does it matter specifically for test code, not just application code?
Ans: A Pull Request is a request to merge one branch’s changes into another (typically main), which usually triggers a review by teammates before the changes are actually merged in. This matters for test code because a poorly written test — one using a brittle locator, a hardcoded wait, or unclear intent — can quietly cause ongoing flakiness or confusion for an entire team if it merges into a shared suite without anyone reviewing it first; code review is just as valuable for catching bad test-writing habits early as it is for catching bugs in application code.
Exercises — Part 5
Understand:
Without looking anything up, explain in your own words the difference between git add, git commit, and git push — specifically, what each one actually does, and why all three are separate steps rather than one single action.
Simple Practice:
If you don’t already have one, create a free GitHub account and a new empty repository. Locally, initialize a Git repo in a test folder (git init), create a .gitignore file listing node_modules/, test-results/, playwright-report/, and .env, then make your first commit containing just that .gitignore file, with a clear, specific commit message.
Real-World Scenario:
You and a teammate are both working on the same Playwright test suite. You’re adding tests for the checkout flow; they’re fixing a flaky login test. Write out, step by step, the sequence of Git commands each of you would realistically run — from starting your work to your changes safely existing on main — assuming you both want to avoid overwriting each other’s work.
Challenge:
Imagine you just committed a change that broke several tests, and you want to see exactly what changed in that specific commit, without undoing anything yet. Research (using Git’s own documentation or git help) which command would show you the exact differences introduced by a specific past commit, and write down the command along with a one-sentence explanation of what it does.
Next: Part 6 — Playwright Fundamentals
— this is it: Node.js is installed, npm is understood, TypeScript makes sense, Git is ready to track your work. It’s time to actually install Playwright and write your first real test.
- Author
- TechByteByByte Editorial Team
- Reviewed by
- TechByteByByte Admin
- Published
- Last reviewed