Git for QA
You don't need to be a Git expert to be a great QA engineer, but you do need a working set of commands you reach for daily — pulling latest, switching to a feature branch, resolving conflicts in test files, and finding the commit that broke a passing test. This sheet is that working set.
Setup & config
One-time setup on a new machine.
# Identity — used on every commit you author
git config --global user.name "Jane Tester"
git config --global user.email "jane@example.com"
# Editor for commit messages and rebases
git config --global core.editor "code --wait"
# Better diffs and merges
git config --global merge.conflictstyle diff3
# Show short hashes everywhere
git config --global log.abbrevCommit true
# View all settings
git config --listCloning a repo and creating one from scratch:
# Clone an existing project
git clone https://github.com/your-team/app.git
cd app
# Or initialise a new repo (e.g., for your test framework)
mkdir qa-automation && cd qa-automation
git initDaily workflow
The four-command loop you'll run a hundred times a week.
# 1. See what's changed locally
git status
# 2. Stage specific files (or everything)
git add tests/login.spec.ts
git add . # everything in cwd
# 3. Commit with a message
git commit -m "Add login retry-on-flaky test"
# 4. Push to the remote branch
git push origin qa/login-retryA safer commit pattern when you're unsure what you've staged:
git diff # unstaged changes
git diff --staged # what's about to be committed
git commit -v # opens editor with the diff for reviewBranching & switching
# Create and switch in one step
git switch -c qa/flaky-login-fix # modern syntax (Git 2.23+)
git checkout -b qa/flaky-login-fix # older syntax — still works
# List branches
git branch # local
git branch -r # remote-tracking
git branch -a # all
# Switch branches
git switch main
git switch - # back to previous branch (like cd -)
# Delete a merged branch
git branch -d qa/old-branch
# Force-delete an unmerged branch (careful)
git branch -D qa/abandoned-experiment
# Rename the current branch
git branch -m qa/better-nameMerge vs rebase
Both integrate changes from one branch into another. They produce different histories.
Merge preserves the actual history with a merge commit:
git switch main
git pull
git switch qa/my-feature
git merge main # main → my-feature, creates merge commitRebase replays your commits on top of the target branch — linear history, no merge commit:
git switch qa/my-feature
git rebase main # replay my commits on top of mainRule of thumb:
| Situation | Use |
|---|---|
| Bringing your local feature branch up to date | rebase (cleaner history) |
Merging a PR into main | merge (preserves the branch context) |
| Branch already pushed and reviewed | merge (don't rewrite shared history) |
| Branch is private (only you have it) | rebase is safe |
If a rebase goes wrong:
git rebase --abort # back to where you started
git rebase --continue # after fixing conflicts in the current step
git rebase --skip # drop the conflicted commit and move onInspecting history
# Compact log — most useful daily view
git log --oneline --graph --decorate --all
# Last 10 commits with files changed
git log -10 --stat
# Search commit messages
git log --grep="login"
# Search code changes
git log -S "loginButton.click" # commits that added/removed this string
# What did a commit change?
git show abc1234
# Who last touched each line of a file?
git blame tests/login.spec.ts
# Show the diff of a single commit
git show abc1234 --statA useful alias for the compact log — add to ~/.gitconfig:
[alias]
lg = log --oneline --graph --decorate --allThen git lg gives you the picture instantly.
Undoing changes
The right "undo" depends on what state the change is in.
# Discard unstaged changes in a file
git restore tests/login.spec.ts
# Unstage a file (keep the edit, just don't commit it yet)
git restore --staged tests/login.spec.ts
# Discard ALL unstaged changes (destructive — be sure)
git restore .
# Undo the last commit but keep the changes staged
git reset --soft HEAD~1
# Undo the last commit and unstage the changes
git reset HEAD~1 # default is --mixed
# Undo the last commit AND discard the changes (very destructive)
git reset --hard HEAD~1
# Undo a commit on a shared branch by creating a new commit that reverses it
git revert abc1234git stash — the "save my work for later" command:
# Stash uncommitted changes
git stash
# Stash with a description
git stash push -m "WIP: login flaky retry"
# List stashes
git stash list
# Re-apply the most recent stash
git stash pop # apply + drop from stash list
git stash apply # apply but keep in stash list
# Apply a specific stash by index
git stash apply stash@{2}
# Discard the top stash
git stash drop
# Stash only specific files
git stash push tests/login.spec.tsWorking with remotes
# View configured remotes
git remote -v
# Fetch from origin without merging — updates remote-tracking branches only
git fetch origin
# Pull = fetch + merge into current branch
git pull origin main
# Pull with rebase instead of merge (cleaner history)
git pull --rebase origin main
# Make rebase the default for `git pull`
git config --global pull.rebase true
# Push to a remote branch (set upstream on first push)
git push -u origin qa/login-retry
# Delete a remote branch
git push origin --delete qa/old-feature
# Prune deleted remote branches from your local view
git fetch --pruneQA scenario: check out a feature branch to test it
# Make sure you have the latest list of remote branches
git fetch origin
# Switch to it (Git auto-tracks the remote branch)
git switch feature/login-fix
# Or with the older syntax
git checkout feature/login-fix
# Pull any updates the developer pushed since
git pullQA scenario: pull latest changes before testing
# On your current branch
git pull --rebase origin main
# Or if you specifically want main's latest
git switch main
git pullQA scenario: branch for your test automation code
# Branch off main
git switch main
git pull
git switch -c qa/login-retry-suite
# Make changes
git add tests/login-retry/
git commit -m "Add retry-on-flake suite for login flow"
# Push for review
git push -u origin qa/login-retry-suiteQA scenario: resolve merge conflicts in test files
git pull origin main
# CONFLICT (content): Merge conflict in tests/checkout.spec.ts
# 1. Open the conflicted file. You'll see markers:
# <<<<<<< HEAD
# your changes
# =======
# incoming changes
# >>>>>>> origin/main
#
# 2. Edit to keep what you want. Remove all <<<<, ====, >>>> markers.
#
# 3. Mark the file resolved
git add tests/checkout.spec.ts
# 4. Continue the merge or rebase
git commit # if merging
git rebase --continue # if rebasing
# Bail out if you got in over your head
git merge --abort
git rebase --abortFor test files specifically: when in doubt, keep both test cases. A test removed in the conflict is one less safety net.
QA scenario: bisect to find the commit that broke a test
When a test was passing last week and now it isn't, git bisect finds the breaking commit in log₂(N) steps.
# Start the bisect
git bisect start
# Tell Git the current commit is broken
git bisect bad
# Tell Git the last known good version (a tag, hash, or branch)
git bisect good v1.4.0
# Git now checks out a commit halfway between them.
# Run your test against this commit:
npm test -- tests/checkout.spec.ts
# Mark the result and Git will narrow further
git bisect good # if the test passed
git bisect bad # if the test failed
# Keep marking. After ~log2(N) iterations, Git prints:
# abc1234 is the first bad commit
# Reset back to your branch
git bisect resetYou can fully automate it if you have a script that returns 0 for "good" and non-zero for "bad":
git bisect start HEAD v1.4.0
git bisect run npm test -- tests/checkout.spec.tsWalk away — Git will hand you the offending commit.