This is the lesson you actually run on your laptop. Open a terminal, follow the commands, paste the output back into your notes when something feels surprising. By the end you'll have a real merged PR, a working pre-push hook, and three forensic answers from your repo's history. Every command that appears here was covered in detail in earlier chapters — the walkthrough is about practising them in sequence, not learning new ones.
Step 0 — preflight
git --version
git config --list | grep -E "user.name|user.email"
ssh -T git@github.comYou should see a Git version, your name + email, and (for SSH users) Hi <username>! You've successfully authenticated. If anything is missing, fix it before continuing — Chapter 1 Lesson 2 and Chapter 3 Lesson 1 cover the setup.
Step 1 — set up the project
On GitHub, click New repository. Name it git-for-qa-capstone, public, add a README, and pick Node from the .gitignore template. Click Create.
Locally:
cd ~/projects
git clone git@github.com:<your-username>/git-for-qa-capstone.git
cd git-for-qa-capstone
git status
git log --onelineExpected log:
a1b2c3d Initial commit
Now scaffold the test project:
npm init -y
npm install --save-dev cypress
mkdir -p cypress/e2e cypress/fixturesCreate a minimal cypress.config.ts at the root:
cat > cypress.config.ts << 'EOF'
import { defineConfig } from 'cypress';
export default defineConfig({
e2e: {
baseUrl: 'https://example.cypress.io',
defaultCommandTimeout: 5000,
video: false
}
});
EOFCreate five starter test files (placeholders for "the team's existing tests"):
for n in add-todo complete-todo delete-todo filter-todos persist-todos; do
echo "describe('$n', () => { it.skip('placeholder', () => {}); });" > cypress/e2e/$n.cy.ts
doneAdd one fixture:
cat > cypress/fixtures/todos.json << 'EOF'
[
{ "id": 1, "text": "Buy milk", "done": false },
{ "id": 2, "text": "Walk the dog", "done": true }
]
EOFStage and commit the starter:
git add .
git commit -m "Scaffold Cypress project with 5 starter tests and fixture"
git pushgit log --onelineb2c3d4e Scaffold Cypress project with 5 starter tests and fixture
a1b2c3d Initial commit
You're set up. Two commits on main, a clean working tree, push working silently.
Step 2 — branch and add three tests
git switch -c feature/todo-edit-casesCreate three new test files. Use any plausible content — the point is the workflow, not the test logic:
cat > cypress/e2e/edit-todo.cy.ts << 'EOF'
describe('edit a todo', () => {
it('updates text on inline edit', () => {});
it('keeps state when clicking outside without saving', () => {});
});
EOF
cat > cypress/e2e/keyboard-shortcuts.cy.ts << 'EOF'
describe('todo keyboard shortcuts', () => {
it('deletes a todo with the Delete key', () => {});
});
EOF
cat > cypress/e2e/mark-all-complete.cy.ts << 'EOF'
describe('mark all complete', () => {
it('toggles every todo to done in one click', () => {});
});
EOFCommit each as a separate, well-named commit:
git add cypress/e2e/edit-todo.cy.ts
git commit -m "Add edit-todo tests for inline edit and unsaved-state cases"
git add cypress/e2e/keyboard-shortcuts.cy.ts
git commit -m "Add keyboard-shortcut test for Delete-key todo removal"
git add cypress/e2e/mark-all-complete.cy.ts
git commit -m "Add mark-all-complete test for bulk toggle"
git log --oneline -53a7b2c1 Add mark-all-complete test for bulk toggle
9b3d2f1 Add keyboard-shortcut test for Delete-key todo removal
4c48901 Add edit-todo tests for inline edit and unsaved-state cases
b2c3d4e Scaffold Cypress project with 5 starter tests and fixture
a1b2c3d Initial commit
Push the branch with -u:
git push -u origin feature/todo-edit-casesStep 3 — update .gitignore
Imagine a visual-regression tool started writing files to cypress/visual-snapshots/. Add the pattern:
cat >> .gitignore << 'EOF'
# Visual-regression artefacts
cypress/visual-snapshots/
EOFCreate a fake artefact and confirm it's invisible:
mkdir -p cypress/visual-snapshots
echo "fake png" > cypress/visual-snapshots/login.png
git statusThe folder should NOT appear in git status. Verify with:
git check-ignore -v cypress/visual-snapshots/login.pngCommit the .gitignore update:
git add .gitignore
git commit -m "Ignore cypress/visual-snapshots/ artefacts"
git pushStep 4 — manufacture and resolve a merge conflict
Switch to main and edit the config:
git switch main
git pullEdit cypress.config.ts — change defaultCommandTimeout: 5000 to defaultCommandTimeout: 8000. Commit:
git add cypress.config.ts
git commit -m "Bump default timeout to 8s for slower staging"
git pushSwitch back to your feature branch and edit the same line differently:
git switch feature/todo-edit-casesOpen cypress.config.ts and change defaultCommandTimeout to 12000 (a different value from main's 8000). Commit:
git add cypress.config.ts
git commit -m "Bump timeout to 12s for keyboard-shortcut tests"Now merge main in:
git merge mainAuto-merging cypress.config.ts
CONFLICT (content): Merge conflict in cypress.config.ts
Automatic merge failed; fix conflicts and then commit the result.
Open cypress.config.ts. You'll see:
<<<<<<< HEAD
defaultCommandTimeout: 12000,
=======
defaultCommandTimeout: 8000,
>>>>>>> mainResolve. Pick 12000 (your version is the more conservative for the new keyboard-shortcut test), delete all three markers, save. Then:
git add cypress.config.ts
git status
git commitGit opens an editor with a default merge message — accept it. Confirm with:
git log --oneline --graph -8You should see the merge commit visible as a branching-and-rejoining shape.
git pushStep 5 — open a PR with a real description
On GitHub, your branch now has a "Compare & pull request" banner. Click it. Use this description:
## What this PR does
Adds 3 new Cypress tests covering todo edit, keyboard shortcuts, and
mark-all-complete. Also updates `.gitignore` to suppress visual-snapshot
artefacts written by the new visual-regression tool.
## Why
Existing tests cover add/complete/delete/filter/persist but miss the
high-value edit and bulk-action paths. These were flagged in last sprint's
test coverage review (QA-1421).
## How to run locally
npm install
npx cypress run --spec "cypress/e2e/edit-todo.cy.ts,cypress/e2e/keyboard-shortcuts.cy.ts,cypress/e2e/mark-all-complete.cy.ts"
## Test data dependencies
Uses the existing `cypress/fixtures/todos.json`. No new fixtures needed.
The keyboard-shortcut test bumps `defaultCommandTimeout` to 12000ms in
`cypress.config.ts` — confirmed merged cleanly with main's 8000ms change.Add the tests, qa labels (or whatever your repo uses). Click Create pull request.
If you have a teammate, add them as a reviewer. If you're working solo, leave one self-review comment ("Confirming the timeout was raised intentionally for the Delete-key test") to practise the comment workflow.
Step 6 — set up a Husky pre-push hook
Back in the terminal:
npm install --save-dev husky
npx husky inithusky - created .husky/
husky - created .husky/pre-commit
Replace .husky/pre-push with a real check. Create the file:
cat > .husky/pre-push << 'EOF'
#!/bin/sh
echo "Running pre-push checks..."
npm test 2>/dev/null || echo "(no test script defined; skipping)"
echo "✅ Pre-push checks passed."
EOF
chmod +x .husky/pre-pushCommit:
git add .husky package.json package-lock.json
git commit -m "Add Husky pre-push hook for local check gate"
git pushConfirm the hook fires on push — you should see "Running pre-push checks..." in the terminal output before the push completes.
Step 7 — three forensic questions
The repo has enough history now to play history-detective. Run each command and read the output carefully.
How many commits has cypress.config.ts had?
git log --oneline -- cypress.config.tsYou should see 3-4 commits — the scaffold, your timeout bump, main's timeout bump, the merge.
What's the diff between main and your branch in cypress/?
git diff main..feature/todo-edit-cases -- cypress/You should see the three new test files plus the resolved config. Read the hunks; this is exactly what the reviewer sees in the PR's Files Changed tab.
Who last changed line 12 of cypress.config.ts?
git blame -L 12,12 cypress.config.ts9f2e3b4 (You 2026-05-05 14:22 12) defaultCommandTimeout: 12000,
You'll see your most recent commit. Then dig into it:
git show 9f2e3b4The full commit, its message, and the diff. That's the workflow you'll run dozens of times a week investigating real bugs.
The full capstone in motion
Step 1 of 8
Clone + scaffold
git clone, npm init, npm install cypress, scaffold tests + fixture, commit + push.
Final cleanup
After the PR merges, return to a clean state:
git switch main
git pull
git branch -d feature/todo-edit-cases
git push origin --delete feature/todo-edit-cases
git log --oneline --graph -10You should see your three test commits plus the merge, all on main, no leftover branches, working tree clean.
What you just did
In about three hours of focused work, you:
- Set up a brand-new project with sensible defaults and pushed it to GitHub.
- Branched, made multiple atomic commits, and pushed.
- Updated
.gitignoreand verified it. - Manufactured a real merge conflict and resolved it cleanly.
- Opened a PR with a description that any reviewer would respect.
- Configured a team-shareable Git hook.
- Investigated history with three different tools.
That's a fluent QA Git workflow. There's nothing left in this course you haven't either practised or read about. The next (and final) lesson is for review, reflection, and the optional polish that takes you from "got it working" to "I'd be happy to maintain this."