Why QA Engineers Need Git
Every professional test automation project uses version control. Git is the industry standard. As a QA automation engineer, you will:
- Store test code in repositories alongside application code
- Create branches for new test suites and features
- Submit pull requests for code review
- Resolve merge conflicts when multiple people edit tests
- Use Git history to understand when and why tests changed
- Integrate with CI/CD pipelines that trigger on Git events
Essential Git Commands
Setting Up
# Configure your identity
git config --global user.name "Your Name"
git config --global user.email "your.email@company.com"
# Clone a repository
git clone https://github.com/company/test-automation.git
cd test-automation
# Check current status
git status
Daily Workflow Commands
# Get latest changes from remote
git pull origin main
# Create a new branch for your work
git checkout -b feature/add-login-tests
# Check which files you changed
git status
git diff
# Stage specific files
git add tests/login.spec.ts
git add tests/fixtures/users.json
# Commit with a descriptive message
git commit -m "Add login page test suite with positive and negative scenarios"
# Push your branch to remote
git push origin feature/add-login-tests
Viewing History
# View commit history
git log --oneline -20
# See what changed in a specific commit
git show abc1234
# See who last modified each line of a file
git blame tests/login.spec.ts
# Find when a test was added or modified
git log --follow tests/checkout.spec.ts
Branching Strategy for Test Code
Branch Naming Conventions
Use clear, descriptive branch names:
feature/add-checkout-tests # New test suite
feature/POM-login-page # New page object
fix/flaky-search-test # Fix a flaky test
refactor/base-test-class # Refactor existing code
chore/update-playwright-version # Dependency update
The Feature Branch Workflow
main ─────────────────────────────────────────
\ /
feature/add-login-tests ─────
- Create a branch from
main - Make your changes and commit
- Push to remote and open a pull request
- Get code review from teammates
- CI runs your tests automatically
- Merge after approval
Keeping Your Branch Updated
# While working on your branch, main may have new commits
git checkout main
git pull origin main
git checkout feature/add-login-tests
git rebase main
# Or merge main into your branch
git merge main
The Pull Request Process
Creating a Good PR for Test Code
A good pull request includes:
Title: Clear description of what tests are added/changed
Add login page E2E tests with edge cases
Description:
## What
- Added 12 test cases for the login page
- Covers positive login, invalid credentials, account lockout, SSO
## Test Coverage
- Happy path: valid email/password login
- Negative: wrong password (3 attempts → lockout)
- Edge cases: SQL injection in email field, XSS in password
- SSO: Google and GitHub OAuth flows
## Page Objects Added
- LoginPage: login(), forgotPassword(), socialLogin()
- DashboardPage: verifyWelcome(), logout()
## How to Run
npm run test:login
Code Review Checklist for Test Code
When reviewing test PRs, check for:
- Tests have clear, descriptive names
- No hardcoded test data (use fixtures or factories)
- Proper use of page objects (no raw selectors in tests)
- Assertions are specific and meaningful
- Tests are independent (no order dependency)
- Cleanup is handled (test data, browser state)
- No unnecessary waits or sleeps
Handling Merge Conflicts
Merge conflicts happen when two people edit the same file. In test automation, this commonly occurs in:
- Shared page objects
- Test configuration files
- Test data files
Resolving a Conflict
# When you see a conflict after merge or rebase
# Git marks the conflicting sections:
<<<<<<< HEAD (your changes)
async login(email, password) {
await this.page.fill('#email-v2', email);
}
=======
async login(email, password) {
await this.page.fill('[data-testid="email"]', email);
}
>>>>>>> main (incoming changes)
# Resolve by choosing the correct version or combining both
async login(email, password) {
await this.page.fill('[data-testid="email"]', email);
}
# Then stage and commit
git add tests/pages/login.page.ts
git commit -m "Resolve merge conflict: use data-testid selector for email"
.gitignore for Test Projects
A proper .gitignore prevents unnecessary files from cluttering the repository:
# Test results and reports
test-results/
playwright-report/
allure-results/
allure-report/
coverage/
# Screenshots and videos from test runs
screenshots/
videos/
traces/
# Dependencies
node_modules/
.venv/
# IDE files
.vscode/
.idea/
*.swp
# Environment files with secrets
.env
.env.local
# OS files
.DS_Store
Thumbs.db
# Build output
dist/
build/
Git Hooks for Test Quality
Git hooks run scripts automatically at specific Git events. Use them to enforce test quality:
Pre-Commit Hook
Run linting before every commit:
#!/bin/sh
# .git/hooks/pre-commit
npx eslint tests/ --ext .ts,.js
if [ $? -ne 0 ]; then
echo "Linting failed. Fix issues before committing."
exit 1
fi
Pre-Push Hook
Run tests before pushing:
#!/bin/sh
# .git/hooks/pre-push
npx playwright test --grep @smoke
if [ $? -ne 0 ]; then
echo "Smoke tests failed. Fix before pushing."
exit 1
fi
Advanced Git for QA
Stashing Work in Progress
# Save uncommitted changes temporarily
git stash save "WIP: checkout tests"
# Switch to another branch to fix something urgent
git checkout fix/flaky-login-test
# Come back and restore your work
git checkout feature/checkout-tests
git stash pop
Cherry-Picking a Fix
# Apply a specific commit from another branch
git cherry-pick abc1234
Bisecting to Find When a Test Broke
# Find which commit introduced a bug
git bisect start
git bisect bad # Current commit is broken
git bisect good abc1234 # This old commit was working
# Git checks out a middle commit — run your test
npx playwright test tests/login.spec.ts
# Tell Git the result
git bisect good # or git bisect bad
# Repeat until Git finds the culprit commit
git bisect reset # When done
Collaboration Best Practices
Commit Message Guidelines
# Good commit messages
git commit -m "Add checkout flow E2E tests for guest and registered users"
git commit -m "Fix flaky product search test: increase wait timeout for API response"
git commit -m "Refactor LoginPage: extract form fill methods to BaseFormPage"
# Bad commit messages
git commit -m "fix tests"
git commit -m "update"
git commit -m "WIP"
Atomic Commits
Each commit should be a logical unit:
- One commit per feature or fix
- Tests should pass after each commit
- Do not mix unrelated changes
Exercise: Git Workflow Practice
Practice the following workflow:
- Clone a test repository (or create a new one)
- Create a branch
feature/add-search-tests - Add a test file
tests/search.spec.tswith two test cases - Commit with a descriptive message
- Create a second branch
feature/add-filter-testsfrom main - Modify the same configuration file on both branches
- Merge both branches and resolve any conflicts
- View the commit history with
git log --graph --oneline
Key Takeaways
- Use feature branches for all test code changes
- Write descriptive commit messages explaining what and why
- Always pull latest changes before starting new work
- Handle merge conflicts by understanding both changes
- Use .gitignore to keep test results and reports out of the repo
- Git hooks automate quality checks before commit and push