Core Git Best Practices
Following Git best practices helps maintain a clean repository, improves team collaboration, and makes the project easier to maintain.
These practices reduce merge conflicts, improve code quality, and keep the commit history meaningful.
Interview Answer
"I follow Git best practices to ensure clean, manageable, and collaborative code. I commit frequently with meaningful messages, use feature branches for development, synchronize regularly with the remote repository, avoid force pushing on shared branches, use a
.gitignorefile to exclude unnecessary files, submit changes through Pull Requests, and keep the Git history clean by squashing commits when appropriate." A closely related topic: Git Stash, Reset & Revert.
Core Git Best Practices
1. Commit Frequently with Clear Messages
Create small, logical commits instead of large commits containing multiple unrelated changes.
Good commit messages should clearly explain:
- What changed
- Why it changed
Example:
Add login page validation
Fix user authentication bug
Update API error handling
For anything non-trivial, add a body after a blank line explaining why, and reference the ticket:
Replace fixed sleep with wait for spinner in CheckoutPage
The checkout test failed ~1 in 10 runs in CI because the order
button was clicked while the loading spinner still covered it.
Refs: SHOP-412
Many teams also use the Conventional Commits format — feat:, fix:, test:, refactor:, ci:, docs: — for example test: add negative cases for coupon API. It makes history easy to scan and lets tools generate changelogs.
2. Use Feature Branches
Never develop directly on the main branch.
Instead, create separate branches for:
- New features
- Bug fixes
- Hotfixes
- Experiments
This isolates work and reduces risk.
3. Pull and Synchronize Frequently
Keep your local branch updated with the latest remote changes.
git pull origin main
Benefits:
- Reduces merge conflicts
- Keeps your branch current
- Makes integration easier
4. Avoid Force Push on Shared Branches
Avoid:
git push --force
on shared branches.
Force push is generally safe only on your private feature branch.
When rewriting history is necessary, prefer:
git push --force-with-lease
5. Use .gitignore
Exclude unnecessary files from version control.
Common examples:
- Build folders
- Log files
- Temporary files
- IDE configuration files
- Environment files
Example:
target/
logs/
*.log
.env
.idea/
6. Use Pull Requests (PRs)
Before merging code:
- Create a Pull Request
- Request peer review
- Address review comments
- Merge only after approval
This improves:
- Code quality
- Collaboration
- Knowledge sharing
7. Keep Git History Clean
Maintain a meaningful project history by:
- Making small commits
- Using descriptive commit messages
- Squashing unnecessary commits
- Avoiding unnecessary merge commits
Git Best Practices Workflow
Create Feature Branch
│
▼
Small Commits
│
▼
Pull Latest Changes
│
▼
Create Pull Request
│
▼
Code Review
│
▼
Merge into Main
Benefits of Following Git Best Practices
- Cleaner repository
- Better collaboration
- Easier debugging
- Fewer merge conflicts
- Better code reviews
- Improved project history
- Easier maintenance
Real-Time Example
In my project, every new feature was developed in its own feature branch. We committed frequently with meaningful commit messages, synchronized regularly with the develop branch, submitted Pull Requests for peer review, and squashed unnecessary commits before merging. This kept the main branch stable and the commit history easy to understand.
Branch Naming Conventions
A consistent branch naming convention makes repositories easier to navigate and improves collaboration.
Branch names should clearly indicate:
- The type of work
- A short description
- The associated Jira or work item ID (if applicable)
Interview Answer
"I use meaningful and standardized branch names that include the work type and Jira ticket number. This improves collaboration, traceability, and makes repositories easier to understand."
Common Branch Naming Conventions
| Branch Type | Convention | Example |
|---|---|---|
| Feature | feature/<JIRA-ID>-description |
feature/QA-123-login-page |
| Bug Fix | bugfix/<JIRA-ID>-description |
bugfix/QA-456-fix-login-error |
| Hotfix | hotfix/<issue> |
hotfix/payment-crash |
| Release | release/<version> |
release/1.2.0 |
| Spike / Experiment | spike/<topic> |
spike/new-auth-poc |
Branch Naming Structure
feature/
bugfix/
hotfix/
release/
spike/
Why Is Branch Naming Important?
Consistent naming:
- Identifies the branch purpose
- Links branches to Jira stories
- Improves collaboration
- Supports CI/CD automation
- Simplifies code reviews
- Makes repositories easier to navigate
Real-Time Example
Our team followed branch names like
feature/QA-123-login-pageandbugfix/QA-456-login-error. This allowed everyone to immediately identify the purpose of a branch and trace it back to the corresponding Jira ticket.
Keeping Git History Clean
A clean Git history makes project maintenance much easier.
It simplifies:
- Code reviews
- Release management
- Understanding project evolution
Interview Answer
"I keep Git history clean by creating small logical commits, writing meaningful commit messages, using separate branches for different tasks, squashing unnecessary commits before merging, and avoiding unnecessary merge commits whenever possible."
Best Practices
Create Small Logical Commits
Each commit should represent one logical change.
Instead of:
Fixed login
Updated APIs
Added reports
Changed UI
Create separate commits for each logical task.
Write Meaningful Commit Messages
Example:
Add login validation
Fix password reset issue
Improve API response handling
Use Separate Branches
Avoid mixing unrelated work in the same branch.
Examples:
- Feature branch
- Bug fix branch
- Hotfix branch
Squash Unnecessary Commits
Remove unnecessary commits such as:
WIP
Fix typo
Another fix
Testing
before merging.
Avoid Unnecessary Merge Commits
Keep history as linear as possible whenever appropriate.
Clean History Workflow
Feature Branch
│
▼
Small Commits
│
▼
Squash Commits
│
▼
Merge into Main
The Benefit of Squashing Commits
Squashing combines multiple related commits into a single meaningful commit.
This results in a cleaner and more readable Git history.
Interview Answer
"Before merging feature branches, I usually squash multiple work-in-progress commits into a single meaningful commit. This keeps the main branch history clean and makes code reviews easier."
Benefits of Squashing
- Cleaner commit history
- Easier code reviews
- Removes unnecessary commits
- Better debugging
- More meaningful project history
Before Squashing
Fix typo
Update code
Another fix
Testing
Final changes
After Squashing
Implement Login Feature
When Should You Squash?
Squash commits when:
- Many small commits exist.
- Work-in-progress commits are present.
- Preparing a Pull Request.
- Merging feature branches into the main branch.
Real-Time Example
During feature development, I often make several incremental commits while testing different approaches. Before creating the Pull Request, I squash those commits into a single meaningful commit that clearly describes the completed feature.
Avoiding Merge Conflicts in a Team
Merge conflicts occur when multiple developers modify the same parts of a file.
Good collaboration practices significantly reduce merge conflicts.
Interview Answer
"To minimize merge conflicts, I regularly pull the latest changes, keep my branch synchronized with the base branch, communicate with teammates when working on the same modules, make small commits, and merge changes frequently."
Best Practices
Pull Frequently
git pull origin develop
Keeps your branch updated.
Communicate with the Team
Coordinate work on:
- Shared files
- Common modules
- Large features
Make Small Commits
Small commits are:
- Easier to merge
- Easier to review
- Easier to resolve
Merge Regularly
Do not allow branches to diverge for long periods.
Merge frequently.
Team Collaboration Workflow
Developer A
│
▼
Feature Branch
│
▼
Pull Latest Changes
│
▼
Resolve Small Conflicts
│
▼
Create Pull Request
│
▼
Merge Successfully
Benefits
Following these practices:
- Reduces merge conflicts
- Improves collaboration
- Speeds up code reviews
- Simplifies integration
- Keeps development smooth
Real-Time Example
In our Scrum team, every developer pulled the latest changes before starting work and before creating a Pull Request. We also communicated when multiple developers were working on the same module. This significantly reduced merge conflicts during sprint development.
Enforce It Automatically: A Pre-Commit Hook That Blocks Secrets
Best practices work better when a tool enforces them. Test automation repositories are especially prone to committed secrets — test-user passwords in config.properties, API keys in .env. A Git pre-commit hook runs before every commit and can stop it. Save this as .git/hooks/pre-commit and make it executable (chmod +x):
#!/bin/sh
# Block commits that add obvious secrets or local config files
if git diff --cached --name-only | grep -qE '(^|/)\.env$'; then
echo "pre-commit: .env files must not be committed (add it to .gitignore)"; exit 1
fi
if git diff --cached -U0 | grep -qiE '^\+.*(password|api[_-]?key|token)\s*=\s*[^[:space:]]+'; then
echo "pre-commit: possible secret in staged changes:"
git diff --cached -U0 | grep -iE '^\+.*(password|api[_-]?key|token)\s*=' | sed 's/^/ /'
exit 1
fi
We tested it:
$ git add config.properties && git commit -m "Add QA config"
pre-commit: possible secret in staged changes:
+password=Admin@123
(commit blocked)
# after moving the password to an environment variable (QA_PASSWORD):
$ git commit -m "Add QA config (password from QA_PASSWORD)"
(committed)
$ git add -f .env && git commit -m "Add env"
pre-commit: .env files must not be committed (add it to .gitignore)
(commit blocked)
- Hooks in
.git/hooksare local — they aren't shared through the repository. Teams share them with a tool such as pre-commit or Husky, or a committedhooks/folder plusgit config core.hooksPath hooks. - A hook is a first line of defense, not the only one: also enable secret scanning on the server (for example GitHub's push protection) and in CI, because anyone can skip a local hook with
--no-verify. - If a secret is ever pushed, rotate it immediately — deleting it in a later commit doesn't remove it from history.
Practice Git best-practice questions under interview conditions in the Git Interview Simulator. Related: Pull Requests & Branch Protection.
From Real Projects
In my automation roles I maintained test scripts that several people reviewed and extended — POM classes, the business library and data files all changing at once. That's exactly the situation version control is built for: every change reviewed, traceable and easy to undo. On Canolog, the many forms and screens across sales, inventory, finance and service are where keeping page details in POM classes and reusable steps in a business library paid off. Never commit passwords or tokens — and rotate them immediately if you do.
📚 Official documentation: Git documentation
Frequently Asked Questions (FAQs)
1. What Git best practices do you follow?
I follow several Git best practices, including:
- Committing frequently with meaningful messages
- Using feature branches
- Pulling the latest changes regularly
- Avoiding force pushes on shared branches
- Using a
.gitignorefile - Creating Pull Requests for code review
- Keeping the commit history clean by squashing commits when appropriate
These practices improve collaboration, reduce conflicts, and maintain a clean repository.
2. How do you name your branches?
I use meaningful branch names that include the work type and Jira ticket number.
Examples:
feature/QA-123-login-pagebugfix/QA-456-fix-login-errorhotfix/payment-crashrelease/1.2.0
This improves traceability and collaboration.
3. Why is a consistent branch naming convention useful?
Consistent branch naming:
- Clearly identifies the purpose of a branch
- Links work to Jira stories or tasks
- Makes repositories easier to navigate
- Improves collaboration
- Supports CI/CD automation
- Simplifies release management and code reviews
4. How do you keep your Git history clean?
I maintain a clean Git history by:
- Creating small logical commits
- Writing descriptive commit messages
- Using separate branches for different tasks
- Squashing unnecessary commits before merging
- Avoiding unnecessary merge commits whenever possible
This makes debugging, reviewing, and maintaining the project much easier.
5. What is the benefit of squashing commits?
Squashing combines multiple small commits into a single meaningful commit.
Benefits include:
- Cleaner project history
- Easier code reviews
- Removal of unnecessary work-in-progress commits
- Simplified debugging
- Better maintainability
I typically squash commits before merging feature branches into the main branch.
6. How do you avoid merge conflicts in a team?
I minimize merge conflicts by:
- Pulling the latest changes frequently
- Keeping my branch synchronized with the base branch
- Communicating with teammates when working on shared files
- Making small, focused commits
- Merging or rebasing regularly
- Resolving conflicts as soon as they occur
These practices enable smoother collaboration and significantly reduce the likelihood of complex merge conflicts.