A small team does not need a complicated Git process, but it does need predictable decisions. This checklist covers branch creation, focused commits, rebasing or merging, conflict resolution, pull requests, and releases so each change can move from a local workspace to production with less confusion.
Overview
The right Git branching strategy depends on release frequency, team size, and how safely your application can be deployed. For many small teams, a short-lived feature branch combined with a pull request is a practical default: keep the change narrow, review it before merging, run automated checks, and remove the branch when the work is complete.
Choose one shared rule for the team rather than allowing every contributor to invent a personal workflow. Write the rule in the repository README or contribution guide, and document which branch is protected, which checks are required, and whether pull requests are merged with a merge commit, squash merge, or rebase.
| Model | How it works | Good fit | Trade-off |
|---|---|---|---|
| Trunk-based development | Contributors integrate small changes into one main branch, often using short-lived branches or direct commits where appropriate. | Teams that deploy frequently and have strong automated tests. | Requires disciplined reviews, small changes, and reliable build checks. |
| GitHub Flow | A contributor creates a branch from the main branch, opens a pull request, reviews the change, and merges it back. | Small teams building web applications or services with a single primary release line. | Long-running work can become difficult if branches are not updated regularly. |
| Git Flow | Separate long-lived branches represent development, releases, and sometimes hotfixes. | Products with scheduled releases or multiple supported release lines. | More branch management and more opportunities for divergence. |
For a small team without a strong reason to maintain release branches, GitHub Flow or a lightweight trunk-based process is usually easier to operate than a full Git Flow model. Treat that as a starting assumption, not a permanent rule.
Checklist by scenario
1. Starting a feature, bug fix, or maintenance task
- Update your local view of the remote repository:
git fetch origin. - Move to the team’s integration branch and update it:
git switch main, thengit pull --ff-only origin main. - Create a short, descriptive branch:
git switch -c feat/account-password-reset. Use a consistent prefix such asfeat/,fix/,docs/, orchore/. - Confirm the task has a clear outcome. A branch should normally address one user-visible change, defect, refactor, or maintenance objective.
- Before editing, identify tests, database changes, configuration changes, and documentation that may be affected.
2. Making focused commits
Keep commits understandable and reversible. A commit that mixes a bug fix, formatting changes, dependency upgrades, and unrelated cleanup is harder to review and harder to undo.
- Review the working tree with
git statusbefore staging files. - Inspect changes with
git diffand stage deliberately withgit add <file>orgit add -p. - Write a message that explains the change, such as
fix: reject expired password-reset tokens. - Run focused tests first, then the broader project checks required by the repository.
- Do not commit secrets, local environment files, generated artifacts, or debug output.
A reusable Git commit message template is:
<type>: <short imperative description>
<optional explanation of why the change is needed>
<optional notes about tests, migration, or rollout>
Use a small set of agreed types, or omit the type if your team prefers plain descriptions. Consistency matters more than adopting a particular convention.
3. Updating a branch before review
Before opening or updating a pull request, bring the branch up to date with the target branch. Rebasing creates a linear local history by replaying your commits on top of the latest target branch:
git fetch origin
git rebase origin/main
Rebase only your own unpublished branch, or agree on the rule before rewriting history. If the branch is already shared, merging the target branch may be less disruptive:
git fetch origin
git merge origin/main
After a rebase, a normal push may be rejected because the commit history changed. Use git push --force-with-lease only when you understand the branch ownership and remote state. Do not use an unconditional force push as a routine fix.
4. Resolving a merge conflict
- Read the conflict list with
git status; do not guess which files are affected. - Open each conflicted file and understand both versions before choosing a result. Conflict markers include
<<<<<<<<,=======, and>>>>>>>. - Preserve the intended behavior, not simply “ours” or “theirs.” Combine changes when both are required.
- Stage each resolved file with
git add <file>. - Continue with
git rebase --continueorgit merge --continue, depending on the operation. - Run tests and inspect the final diff. If the resolution is unclear, stop and ask the original author or reviewer.
To abandon an operation you no longer trust, use git rebase --abort or git merge --abort. These commands are safer than trying to manually reconstruct the previous state.
5. Opening and reviewing a pull request
Open the pull request only when the branch is pushed, the description is complete, and local checks have been run. Keep the request narrow enough that reviewers can understand the behavioral change without reconstructing the entire project.
Use this pull request template:
## Summary
- What changed?
- Why was it needed?
## Validation
- [ ] Unit or integration tests passed
- [ ] Manual checks completed, if applicable
- [ ] Documentation or migration updated
## Risk and rollout
- Possible side effects:
- Rollback plan:
- Feature flag or deployment note:
## Review focus
Please pay particular attention to:
Reviewers should check correctness, tests, security-sensitive behavior, error handling, data changes, accessibility where relevant, and whether the implementation matches the stated scope. Authors should respond to comments, push follow-up commits, and mark discussions resolved only after the concern is addressed.
6. Merging and preparing a release
Use the repository’s agreed merge strategy. Squash merging keeps one pull request represented as one commit and can produce a compact main-branch history. A merge commit preserves the branch’s individual commits and relationship to the target branch. Rebasing and fast-forward approaches can provide a linear history but require more care when rewriting branches. Select one default and document exceptions.
Before merging, confirm that required checks are green, approvals are complete, the branch is current enough for the repository policy, and any migration or configuration step is documented. After merging:
- Verify the integration or deployment workflow starts as expected.
- Watch the relevant health checks, logs, or smoke tests.
- Remove the remote feature branch if it is no longer needed.
- Record release notes, version information, or rollback instructions when applicable.
- For a failed release, prefer a documented revert or rollback procedure over an improvised history rewrite.
What to double-check
- Branch protection: Protect the integration and release branches from accidental deletion or direct unreviewed changes. Require the checks and approvals that genuinely reflect project risk.
- Permissions: Confirm who can approve, merge, bypass checks, or push to protected branches. Keep exceptions explicit and limited.
- Automated checks: Ensure the pull request runs the same meaningful tests, linting, formatting, and build validation used before release.
- Secrets: Check diffs and generated files for tokens, credentials, private keys, and sensitive customer data. If a secret is committed, treat it as exposed and follow the team’s rotation procedure.
- Database and API changes: Review compatibility between old and new application versions, especially when deployments are not instantaneous.
- Hosting-platform settings: Interface labels and branch-rule options vary between Git hosting platforms. Verify the current repository settings rather than relying on an old screenshot or remembered menu path.
Common mistakes
- Long-lived feature branches: They accumulate conflicts and make review difficult. Split large work into compatible increments, feature flags, or preparatory changes.
- One giant commit: Separate behavior changes from formatting, generated files, and unrelated refactoring.
- Rebasing shared history: Coordinate before rewriting a branch others use. Prefer
--force-with-leaseover--forcewhen a force push is genuinely needed. - Resolving conflicts mechanically: A file that compiles can still contain the wrong business logic. Test the behavior represented by the conflict.
- Approving without reading the diff: A green build does not prove that the change is correct, secure, or within scope.
- Merging while checks are uncertain: If a check is flaky or skipped, record the reason and decide whether the merge should wait.
When to revisit
Review this Git workflow before seasonal planning cycles, after a release incident, when the team grows, or when the application moves from scheduled releases to frequent deployment. Also revisit it whenever your Git hosting platform changes branch protection, pull request, merge, or automation settings. A six-month review is a useful maintenance habit even when no problem is obvious.
At each review, examine a small sample of recent pull requests: time to review, conflict frequency, rollback clarity, failed checks, and whether branch names and commit messages remain useful. Remove rules that create paperwork without reducing risk, and add guidance where contributors repeatedly make the same mistake.
For your next change, copy this sequence into the task description: update the target branch, create a short-lived branch, make focused commits, run checks, update the branch, open a complete pull request, resolve conflicts deliberately, merge using the team default, and verify the release. Reusing the checklist is more valuable than memorizing every Git command.