Making commits is an art! Professional developers follow rules to keep the project history clean and understandable.
Core Rules
The Golden Rule: 1 Commit = 1 Change
❌ Bad:
# Did everything for the week → 1 commit
git commit -m "week of work"
# 50 files changed, 2000 insertions, 800 deletions 😱
✅ Good:
git commit -m "feat: add user model"
git commit -m "feat: create login form"
git commit -m "fix: fix email validation"
git commit -m "docs: update README"
git commit -m "test: add auth tests"
# = 5 clear commits
Why this matters:
- Easy to understand what changed
- Can revert a specific change
- Code review goes faster
- History reads like a book
Rule 2: Write Clear Commit Messages
Formula: <type>: <what was done>
Commit types:
feat— new featurefix— bug fixdocs— documentationrefactor— refactoringtest— testschore— routine work (dependencies, configs)style— formatting
Examples
✅ Great:
feat: add two-factor authentication support
fix: fix 500 error on empty email
docs: update API endpoints documentation
refactor: simplify form validation logic
test: add unit tests for user service
❌ Bad:
update
fix
done
asdfgh
commit
work
Rule 3: Commit Working Code
❌ Never:
git commit -m "wip" # work in progress - code doesn't work!
Problems:
- Colleagues get broken code
- CI/CD will fail
- Can’t roll back to this commit
✅ Always:
# Before committing:
1. Run the code — does it work?
2. Run tests — all green?
3. Check the linter — no errors?
4. Only then commit!
If you need to save unfinished work:
git stash # stash temporarily
# Work on something else
git stash pop # restore
Rule 4: Review the Diff Before Committing
Always check WHAT you’re committing!
In GitHub Desktop:
1. Changes tab
2. Click on a file
3. Review the diff (green/red)
4. Make sure everything is correct
Common mistakes:
- ❌ Committed console.log() debug output
- ❌ Committed .env with passwords
- ❌ Committed TODO comments
- ❌ Accidentally deleted important code
Rule 5: Use .gitignore
What NOT to commit:
# .gitignore
node_modules/
__pycache__/
.env
*.log
.DS_Store
dist/
build/
Create .gitignore IMMEDIATELY:
# At the start of the project:
1. Create .gitignore
2. Add patterns
3. Commit it
4. Profit — junk won't end up in Git!
Advanced Rules
Rule 6: Write Commit Messages in One Language Consistently
❌ Bad (mixed languages):
git commit -m "fix bug in login function"
git commit -m "add new feature for users"
✅ Good (one language):
# English:
git commit -m "fix: fixed bug in login function"
git commit -m "feat: added new feature for users"
Tip: For open source projects — use English. For your own projects — whatever works for your team.
Rule 7: Add Context in the Description
Summary — brief what, Description — detailed how and why
✅ Example:
Summary:
fix: fix error when uploading avatar
Description:
Problem:
- Uploading PNG > 5MB caused a 500 error
- No file size validation
Solution:
- Added size check (max 5MB)
- Returns 400 with a clear error message
- Updated tests
Fixes #123
Useful when:
- The change is not obvious
- Need to explain “why”
- Linking to an issue/task
- Code review
Rule 8: Commit Often, Push Less Often
Workflow:
# Working locally:
git commit -m "feat: add model"
git commit -m "feat: add form"
git commit -m "feat: add view"
git commit -m "test: tests for view"
# Everything works? Push all at once:
git push
Why:
- Locally — experiment freely
- Push — when everything is done and working
- Can squash commits before push
- Don’t block the team with unfinished code
Rule 9: Don’t Commit Secrets!
❌ DANGEROUS:
# settings.py
SECRET_KEY = "django-secret-123456"
DATABASE_PASSWORD = "password123"
API_KEY = "sk_live_1234567890"
✅ Right approach:
# settings.py
import os
SECRET_KEY = os.getenv('SECRET_KEY')
DATABASE_PASSWORD = os.getenv('DB_PASSWORD')
API_KEY = os.getenv('API_KEY')
# .gitignore
.env
# .env (NOT committed!)
SECRET_KEY=django-secret-123456
DB_PASSWORD=password123
API_KEY=sk_live_1234567890
If already committed:
1. Change passwords IMMEDIATELY!
2. Remove from history (git filter-branch)
3. Force push (dangerous!)
Rule 10: Follow Conventional Commits
Industry standard:
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
Examples:
feat(auth): add two-factor authentication
fix(api): handle null values in user endpoint
docs(readme): update installation instructions
refactor(payment): simplify checkout logic
test(auth): add unit tests for login
chore(deps): update dependencies to latest
Scope (optional) — where the change is:
- auth — authentication
- api — API endpoints
- ui — interface
- db — database
Pre-commit Checklist
- [ ] Code works (ran and verified)
- [ ] Tests pass (if any)
- [ ] Reviewed diff — everything is correct
- [ ] Commit message is clear
- [ ] No secrets in the code
- [ ] No commented-out code
- [ ] No console.log / print for debugging
- [ ] .gitignore is configured
Examples of Good Commit Histories
todo-app project:
feat: initial project setup
feat: add task model and database schema
feat: create API endpoint for task creation
fix: validate task title is not empty
test: add tests for task creation
docs: add API documentation
refactor: extract validation logic to separate function
feat: add task completion functionality
fix: prevent duplicate task creation
docs: update README with usage examples
You can see the evolution of the project! 📈
Anti-patterns (What to Avoid)
❌ “update” commits:
git commit -m "update"
git commit -m "update 2"
git commit -m "final update"
git commit -m "final update forreals"
git commit -m "ok this is final"
❌ Committing the entire project:
git add .
git commit -m "project" # 500 files!
❌ Fixing typos in 10 commits:
git commit -m "fix typo"
git commit -m "fix another typo"
git commit -m "fix typo in fix typo"
...
How to Fix Bad Practices?
If you already committed poorly:
-
Locally (not yet pushed) — can fix:
bash git commit --amend -m "New message" -
Squash commits:
bash git rebase -i HEAD~3 # combine last 3 -
Already pushed — trickier:
- Leave it (lesson learned)
- Or force push (dangerous for team!)
Better: Do it right from the start!
Conclusion
Good commits = clean history = happy team!
The essentials:
1. 1 commit = 1 change
2. Clear messages
3. Working code
4. Review the diff
5. Use .gitignore
Follow these rules — and your GitHub profile will look professional! 🎯
💬 Comments (0)
No comments yet
Be the first to share your opinion about this article!