Gitignore and Practical Tips
.gitignore for Test Artifacts
Test automation generates files that should never be committed. A well-configured .gitignore prevents accidental commits of large binary files, sensitive credentials, and ephemeral test output.
Essential .gitignore for QA Projects
# Test results and reports
test-results/
playwright-report/
coverage/
allure-results/
allure-report/
junit-results/
*.xml.bak
# Screenshots and videos from test runs
screenshots/
videos/
*.png
!src/assets/*.png # Keep intentional assets (note the negation)
# Playwright traces
traces/
*.zip
# Environment and secrets
.env
.env.local
.env.*.local
*.pem
*.key
credentials.json
service-account.json
# IDE and OS files
.idea/
.vscode/settings.json # Keep shared settings, ignore personal ones
.DS_Store
Thumbs.db
# Dependencies
node_modules/
__pycache__/
*.pyc
.venv/
venv/
# Build artifacts
dist/
build/
*.tsbuildinfo
# Temporary files
tmp/
temp/
*.tmp
*.swp
Common .gitignore Mistakes
Forgetting to Ignore Test Outputs
# Forgetting these means test results get committed
# Adding them later does not remove already-tracked files
test-results/
coverage/
Not Handling Negation Patterns
# This ignores ALL .png files, including intentional ones
*.png
# Fix: Use negation to keep specific files
*.png
!src/assets/*.png
!docs/images/*.png
Ignoring Too Much or Too Little
# Too broad: ignores all JSON files (including test data you want to commit)
*.json
# Too narrow: misses test outputs in subdirectories
test-results/*.png # Does NOT match test-results/chromium/screenshot.png
# Fix: Use recursive patterns
test-results/**
Fixing Accidentally Committed Files
If someone already committed a file that should be ignored, adding it to .gitignore does not remove it from tracking. You must explicitly untrack it.
# Remove file from Git tracking without deleting it locally
git rm --cached test-results/report.html
# Remove an entire directory from tracking
git rm -r --cached test-results/
# After removing, add to .gitignore and commit
echo "test-results/" >> .gitignore
git add .gitignore
git commit -m "chore: stop tracking test results, add to .gitignore"
For large files that have been in the history for a while and are bloating the repo, you may need git filter-branch or BFG Repo-Cleaner to rewrite history. This is a destructive operation -- coordinate with the team first.
Practical Git Commands for QA Engineers
Investigating Changes
# See what changed in the last 5 commits (useful for targeted testing)
git log --oneline -5 --stat
# Find all commits that touched a specific test file
git log --follow -- tests/checkout.spec.ts
# See who last modified each line of a test file (find the right person to ask)
git blame tests/checkout.spec.ts
# See the diff between your branch and main (what the PR will show)
git diff main...HEAD
# Show only the names of changed files (great for deciding what to test)
git diff main...HEAD --name-only
# Show changes in a specific file since a specific commit
git diff v2.3.0..HEAD -- tests/checkout.spec.ts
Managing Work in Progress
# Stash your work-in-progress to switch branches for a hotfix
git stash push -m "WIP: refactoring payment tests"
# List all stashes
git stash list
# Apply the most recent stash (keeps it in the stash list)
git stash apply
# Pop the most recent stash (removes it from the stash list)
git stash pop
# Apply a specific stash
git stash apply stash@{2}
# Switch to a different branch, do work, and come back
git stash push -m "WIP: payment tests"
git checkout hotfix/urgent-fix
# ... do the work ...
git checkout feature/my-branch
git stash pop
Undoing Mistakes
# 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
# Discard all uncommitted changes in a specific file
git checkout -- tests/broken-test.spec.ts
# Revert a specific commit (creates a new commit that undoes the changes)
git revert abc123f
# Recover a deleted branch (find the commit hash in reflog)
git reflog
# Find the commit hash of the branch tip
git checkout -b recovered-branch abc123f
Searching History
# Find commits that contain a specific string in the diff
git log -S "data-testid=\"checkout-button\"" --oneline
# Find commits with a message matching a pattern
git log --grep="fix.*flaky" --oneline -i
# Find when a line was added or removed
git log -p -S "waitForTimeout" -- tests/
# Show the commit that last modified a specific line
git log -1 -L 42,42:tests/checkout.spec.ts
Git Workflow Anti-Patterns for QA
| Anti-Pattern | Problem | Fix |
|---|---|---|
| Committing test results | Repository bloats with binary files | Add test-results/ to .gitignore |
| Giant PRs with 50 test files | Impossible to review meaningfully | Split into logical, reviewable chunks |
| Vague commit messages ("fix tests") | No one knows what changed or why | Write descriptive messages: "fix: stabilize checkout test by awaiting API response" |
| Long-lived feature branches | Drift from main, painful merges | Rebase frequently, keep branches short-lived |
| Force-pushing shared branches | Destroys teammates' local history | Only force-push your own branches before review |
Committing .env files |
Credentials exposed in repo history | Add .env to .gitignore, use secrets management |
Not using .gitignore from day one |
Artifacts accumulate, hard to clean up later | Start every project with a comprehensive .gitignore |
Git Configuration Tips
# Set up useful aliases
git config --global alias.st "status"
git config --global alias.co "checkout"
git config --global alias.br "branch"
git config --global alias.lg "log --oneline --graph --decorate --all"
git config --global alias.last "log -1 HEAD --stat"
# Set default branch name
git config --global init.defaultBranch main
# Auto-prune deleted remote branches
git config --global fetch.prune true
# Use a better diff algorithm
git config --global diff.algorithm histogram
# Set up pull to rebase by default (keeps history cleaner)
git config --global pull.rebase true
Git Hooks for Test Quality
Git hooks run scripts automatically at specific points in the Git workflow. They can enforce quality standards locally.
# .git/hooks/pre-commit (or use husky for team-wide hooks)
#!/bin/sh
# Prevent committing .env files
if git diff --cached --name-only | grep -q '\.env'; then
echo "ERROR: Attempting to commit .env file. Aborting."
exit 1
fi
# Prevent committing test.only or describe.only
if git diff --cached | grep -q '\.only'; then
echo "ERROR: Found .only in test files. Remove before committing."
exit 1
fi
# Run lint on staged files
npx lint-staged
Using husky for team-wide hooks:
// package.json
{
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
},
"lint-staged": {
"tests/**/*.ts": ["eslint --fix", "prettier --write"]
}
}
Hands-On Exercise
- Review your project's
.gitignore. Are test results, screenshots, and.envfiles properly ignored? - Check if any test artifacts have been accidentally committed:
git ls-files | grep -E "(test-results|coverage|screenshots)" - Set up the Git aliases listed above and use
git lgto explore your project's history - Practice
git stashto switch branches mid-work and return without losing changes - Use
git log -Sto find when a specific test selector was introduced or changed - Set up a pre-commit hook that prevents committing
.onlyin test files
Interview Talking Point: "I use Git as a QA tool, not just a code storage tool. I use git bisect to binary-search for regression-introducing commits, saving hours of manual investigation. I write PR descriptions that include test evidence and verification steps. I understand branching strategies well enough to adapt my test execution plan -- in trunk-based development I ensure every commit is deployable, while in GitFlow I plan for testing at multiple integration points. I configure .gitignore to keep test artifacts out of the repository, and I use git hooks to prevent common mistakes like committing .only or .env files. I tag releases with test result metadata so we have a clear audit trail of what was verified for each release."