Git Best Practices

Git is a powerful tool, but its power comes with responsibility. Bad habits — vague commit messages, working directly on main, no .gitignore — create problems that multiply over time. Good habits keep a project clean, understandable, and a pleasure to maintain for everyone who touches it.

1. Commit Messages

Write Meaningful Commit Messages

Every commit message should clearly communicate what changed and why. Future developers (including a future self six months from now) should be able to understand each commit without opening the files.

Bad MessageGood Message
fixFix null reference error when user has no profile photo
updateUpdate login form to validate email format on submit
wipAdd initial structure for payment gateway integration
changesRemove deprecated API calls from user service

Commit Message Format (The 7 Rules)

  1. Limit the subject line to 72 characters
  2. Use the imperative mood — "Add feature" not "Added feature"
  3. Capitalize the first word
  4. Do not end the subject line with a period
  5. Separate subject from body with a blank line
  6. Use the body to explain what and why, not how
  7. Reference related issue numbers at the bottom

Example of a Well-Structured Commit

Fix shopping cart total not updating on quantity change

Previously, the cart total was calculated only on page load.
When users changed item quantities without refreshing, the
displayed total remained incorrect.

Added an event listener on quantity input fields to
recalculate and update the total dynamically.

Fixes #127

2. Commit Often, But Meaningfully

Commits should be small and focused — each one doing one logical thing. This makes the history easy to read, makes git bisect effective, and makes reverting specific changes easy.

  • Good: One commit to add a feature, one commit to add its tests, one commit to add its documentation
  • Bad: One massive commit mixing feature code, bug fixes, style changes, and renamed files all together

3. Never Commit Directly to Main

The main branch should always be in a deployable state. All work should happen on feature or fix branches and go through a pull request before reaching main.

# Wrong approach
git switch main
# ... make changes ...
git commit -m "Add feature"
git push origin main

# Right approach
git switch -c feature/user-notifications
# ... make changes ...
git commit -m "Add user notification system"
git push origin feature/user-notifications
# Open pull request for review

4. Pull Before Pushing

Always pull the latest changes from the remote before pushing. This prevents rejection errors and reduces the chance of conflicts building up unnoticed.

git pull origin main
git push origin main

5. Use .gitignore Properly

Set up a .gitignore file at the very beginning of every project. Never commit:

  • Secrets, credentials, or API keys (.env, config.secret.js)
  • Dependencies (node_modules/, vendor/)
  • Build output (dist/, build/, *.class)
  • OS/editor files (.DS_Store, .idea/, *.swp)
  • Log files (*.log)

6. Use Branches for Everything

Create a new branch for every feature, bug fix, experiment, or even documentation update. Branch names should be descriptive:

feature/user-profile-settings
fix/cart-total-calculation
docs/update-api-reference
chore/update-dependencies
refactor/extract-auth-service

7. Keep Branches Short-Lived

Long-lived feature branches accumulate divergence from main and lead to painful merges. Keep branches focused on a single task and merge them back quickly — ideally within days, not weeks.

8. Review Before Committing

Before every commit, review what is about to be committed:

git diff --staged   # See exactly what will be committed
git status          # Confirm no accidental files are staged

9. Use Tags for Releases

Mark every production release with an annotated tag using semantic versioning:

git tag -a v1.2.0 -m "Release v1.2.0 — Add payment integration"
git push origin --tags

10. Write a Good README

Every project repository should have a README.md that explains:

  • What the project does
  • How to install and run it locally
  • How to run tests
  • How to contribute
  • License information

11. Never Force Push to Shared Branches

git push --force on a shared branch overwrites remote history and destroys other people's work. Only force push on personal branches that no one else is using:

# NEVER do this on shared branches
git push --force origin main  ← Dangerous!

# Safer alternative on shared branches — always use revert
git revert <bad-commit-hash>
git push origin main

12. Protect the Main Branch on GitHub

Enable branch protection rules on GitHub for the main branch:

  1. Go to Repository → Settings → Branches
  2. Click "Add rule" for main
  3. Enable: "Require a pull request before merging"
  4. Enable: "Require status checks to pass before merging" (run tests automatically)
  5. Enable: "Include administrators" (protects from accidental direct pushes)

13. Rebase Feature Branches Before Merging

Before merging a feature branch, rebase it onto the latest main to produce a clean, linear history:

git switch feature/user-profile
git rebase main
git switch main
git merge --no-ff feature/user-profile

14. Clean Up Merged Branches

After a branch is merged, delete it to keep the repository clean:

# Delete local branch
git branch -d feature/user-profile

# Delete remote branch
git push origin --delete feature/user-profile

15. Avoid Storing Large Binary Files

Git is optimized for text files (source code). Storing large binary files (images, videos, binaries) in a Git repository makes it slow and bloated over time. Use Git LFS (Large File Storage) for large binary assets.

Quick Reference Checklist

PracticeStatus
Set up .gitignore before first commitEssential
Write meaningful commit messagesEssential
Use feature branches for all workEssential
Never commit secrets or credentialsCritical
Pull before pushingEssential
Protect the main branch on GitHubHighly Recommended
Review staged changes before committingRecommended
Tag all releasesRecommended
Delete merged branchesGood Practice
Write a good READMEGood Practice

Summary

Good Git practices are not just about using the right commands — they are about creating a shared history that the whole team can understand and work with confidently. Write clear commit messages, use branches for every change, protect the main branch, and never commit secrets. These habits transform Git from a source of confusion into a powerful, reliable foundation for every project.

Leave a Comment

Your email address will not be published. Required fields are marked *