Most Git problems do not come from “advanced” features. They come from teams trying to move fast with half-understood workflows. This post is a practical, intermediate-level playbook: the habits and commands that keep your history clean, your pull requests readable, and your merges calm—even with multiple contributors pushing every day.
If you already know git add, git commit, and git push, this is your next
step. The goal is to make Git feel predictable under team pressure.
The intermediate mental model (why this matters)
Git is a content-addressed database. Every commit is a snapshot, and branches are just pointers to those snapshots. That matters because it means:
- You can rearrange history when it is safe.
- You should avoid rewriting shared history.
- You can always recover lost commits if you know where to look.
Intermediate Git is the skill of editing snapshots without confusing your team.
1) A branch strategy that keeps PRs small
Start with a simple, repeatable pattern:
main: always deployable, protectedfeature/*: short-lived brancheshotfix/*: urgent production fixes
Branch naming should describe intent and scope, not the ticket number. Examples:
feature/add-billing-portalfeature/otp-loginhotfix/invoice-tax-bug
Why it works: If the branch name tells the story, the PR title writes itself.
Branch lifecycle (the rule that saves teams)
- Create a branch for one outcome.
- Keep the branch under ~5 commits when possible.
- Merge or delete quickly.
Long-lived branches accumulate conflict debt. The shorter the branch, the cheaper the merge.
2) Fetch, rebase, merge: make the right choice
The most important intermediate skill is knowing when to rebase and when to merge.
Use rebase when:
- Your branch is private (only you are working on it).
- You want a clean, linear history before opening a PR.
Use merge when:
- Your branch is shared.
- The PR is already in review.
- You want to preserve the true timeline.
Typical workflow:
# Bring main into your branch without a merge commit
git fetch origin
git rebase origin/main
If conflicts appear during a rebase, resolve them once and keep going:
git add <file>
git rebase --continue
Team guideline: Never rebase a branch that another person is actively using.
3) Clean commits with interactive rebase
Interactive rebase turns “four messy commits” into “one clean story.” It is the single highest-leverage command for readable PRs.
git rebase -i origin/main
In the editor:
pickkeeps a commitrewordupdates the messagesquashmerges into the previous commit and lets you edit the messagefixupmerges silently (keeps previous message)dropdeletes a commit from history
Rule of thumb: One commit should represent one logical change.
Example: squashing noisy commits
Before:
WIP: formFix lintAdd validationOops
After rebase:
Add form validation and error messages
This does not “hide” work; it presents it clearly.
4) Commit messages that help reviewers (and your future self)
A clean commit with a vague message is still hard to review. You do not need a strict format, but you do need consistency. A good commit message answers: “What changed, and why?”
A simple, scalable pattern:
<verb> <object> <context>
Examples:
Add validation rules for bulk editFix pagination crash in user listRefactor audit log formatter
If your team uses Conventional Commits, you can apply it without ceremony:
feat: add OTP fallback for login
fix: prevent empty invoices from exporting
Rule of thumb: If you cannot describe the commit in one line, the commit is likely too large.
5) Conflict resolution without redoing the same work
Conflicts are not bad. Re-solving the same conflict is bad. Git can remember how you resolved a conflict and reuse it.
Enable rerere once:
git config --global rerere.enabled true
Now, when a familiar conflict appears, Git can apply your previous resolution.
A fast conflict routine
- Run
git statusto see the conflicted files. - Open the file and resolve markers.
- Run
git add <file>. - Continue the rebase or merge.
Make conflicts readable
Use diff3 to see the base version:
git config --global merge.conflictstyle diff3
This helps you understand why the conflict exists, not just what changed.
Resolve with “ours” or “theirs” when appropriate
When you know which side you want entirely, be explicit:
# Keep your version
git checkout --ours path/to/file
# Keep incoming version
git checkout --theirs path/to/file
Then add and continue.
6) Stage cleanly with patch mode
If your commit contains unrelated changes, review becomes slow. The simplest fix is patch staging.
git add -p
You can stage only the lines that belong to the current commit and leave the rest for later. This is the fastest path to clean commit history.
Tip: Follow it with:
git diff --staged
This is your last chance to verify the snapshot before it becomes history.
7) Stash less, switch context more cleanly
Stash is useful, but it is easy to forget what you saved. When the context switch is larger than a few minutes, prefer a branch or worktree.
Temporary stashing
git stash push -m "wip: search filter"
git stash list
git stash apply stash@{0}
Worktrees (better for longer detours)
git worktree add ../repo-hotfix hotfix/urgent
You get a second working directory with shared Git history. This is cleaner than stashing large changes and safer than mixing two tasks in one tree.
8) Cherry-pick and revert: surgical tools for teams
Cherry-pick for targeted fixes
git cherry-pick <commit-sha>
This copies a single commit onto your current branch. Perfect for backporting a fix to a release branch.
Revert for shared history
git revert <commit-sha>
Revert creates a new commit that undoes a change, which is safer than reset
when you have already pushed to the remote.
9) Pull request hygiene: quality over speed
Good PRs are smaller, not slower. Here is a repeatable checklist.
Pre-PR checklist
- Rebase on
main(or merge if shared) - Run tests locally
- Remove debug logs
- Review your own diff
- Ensure commits are clean and named
PR structure that reviewers love
- One clear goal
- Small diff where possible
- Commit messages that match the narrative
- A short summary and a focused testing note
A simple PR summary template
Use this when you are not sure what to write:
- What changed: One or two sentences describing the change
- Why it changed: The user or system problem being solved
- How to test: A short, reproducible checklist
Reviewers move faster when they do not have to reverse engineer your intent.
10) A realistic daily workflow (intermediate)
# Start the day
git status -sb
git fetch origin
git rebase origin/main
# Work on a change
git add -p
git diff --staged
git commit -m "Add bulk edit validation"
# Push for review
git push -u origin feature/bulk-edit-validation
11) Common mistakes (and their fixes)
| Mistake | Why it hurts | Fix |
|---|---|---|
| Rebasing a shared branch | Causes history divergence and force-push conflicts | Merge or coordinate rebase before anyone pulls |
| Committing unrelated changes together | Review becomes slow and reversions are risky | Use git add -p to stage only related lines |
| Long-lived feature branches | Conflicts pile up, context gets stale | Slice work smaller and merge more often |
| Force-pushing to main | Breaks teammates’ local branches | Protect main and use PRs only |
| Using stash as long-term storage | Work gets lost or forgotten | Create a branch or worktree for long detours |
12) Fast history views when you need clarity
When a PR is large or a conflict appears, you need context quickly. These history views are reliable and fast:
git log --oneline --graph --decorate --all
To focus on a file:
git log -- path/to/file
To understand why a line exists:
git blame -w path/to/file
These commands turn “I think this changed last week” into a concrete answer.
13) A quick intermediate Git checklist
- Use rebase for private branches, merge for shared branches
- Keep commits small and message them like headlines
- Resolve conflicts once and let rerere help next time
- Prefer worktrees over heavy stashing
- Open PRs early but keep them scoped
Conclusion
Intermediate Git is about reliability. You are not just saving your own work; you are shaping how your team reads and trusts that work. Clean branches, intentional rebases, and thoughtful PRs scale far better than brute force.
Once these habits feel natural, advanced Git becomes less scary—because you are already working with the grain of the system, not against it.
Ready to turn daily Git work into visible progress? Join GitRank to track your momentum, compare with peers, and keep your streaks honest.