A concise, actionable checklist of Git workflow best practices to keep your repository clean, collaborative, and maintainable.
1. Use a branching strategy consistently
Adopt a well-known model such as Git Flow, GitHub Flow, or trunk-based development and enforce it across the entire team. Consistency prevents integration chaos and makes the branch purpose immediately clear to all contributors.
2. Name branches with a structured convention
Prefix branches with a type and scope, e.g. feat/user-auth, fix/login-redirect, or chore/update-deps. This makes branch lists scannable and integrates cleanly with issue trackers.
3. Write atomic, single-purpose commits
Each commit should represent one logical change so it can be reverted, cherry-picked, or reviewed in isolation. Avoid bundling unrelated fixes or features into a single commit.
4. Write descriptive commit messages using the 50/72 rule
Keep the subject line under 50 characters, leave a blank line, then wrap the body at 72 characters explaining *why* the change was made. Reference issue numbers (e.g. Closes #42) when applicable.
5. Never force-push to shared or protected branches
Force-pushing rewrites history that teammates have already pulled, causing divergent states and data loss. Reserve force-push only for personal/draft branches, and prefer --force-with-lease over --force.
6. Rebase feature branches before merging
Run git rebase main (or the target branch) on your feature branch before opening a pull request to resolve conflicts early and produce a linear, readable history.
7. Use pull requests for all changes to main/production
PRs enforce code review, trigger CI pipelines, and create a documented audit trail for every change. Even solo developers benefit from the checkpoint a PR provides.
8. Require at least one code review approval before merging
Peer review catches bugs, enforces coding standards, and spreads knowledge across the team. Configure branch protection rules in GitHub/GitLab to block merges without approval.
9. Integrate CI checks as merge gates
Configure your CI pipeline to run linting, tests, and security scans on every PR and block merging if any check fails. This keeps main always in a deployable state.
10. Keep pull requests small and focused
Aim for PRs under 400 lines of diff; smaller PRs are reviewed faster, produce higher-quality feedback, and are easier to revert if something goes wrong.
11. Tag releases with semantic versioning
Use annotated tags (git tag -a v1.4.2 -m 'Release notes here') that follow semver (MAJOR.MINOR.PATCH) so consumers and deployment pipelines can reason about compatibility and change severity.
12. Use a .gitignore and never commit secrets
Maintain a project-specific .gitignore to exclude build artifacts, IDE files, and OS metadata. Use tools like git-secrets or pre-commit hooks to block accidental commits of API keys and passwords.
13. Stash or commit work-in-progress before switching contexts
Use git stash push -m 'description' or a draft commit to preserve incomplete work before switching branches, preventing unintended file bleed-over between contexts.
14. Periodically prune stale remote branches
Delete merged remote branches immediately after merging (automate this in your PR settings) and run git remote prune origin locally to keep the branch list clean and navigation fast.