Collaboration
Remotes, pull requests, resolving conflicts, and code review flow.
Collaboration
Git was designed for distributed teams. The remote model, conflict resolution, and code review flow are where most of the day-to-day friction lives.
Analogy
Collaborating with git is like a group of authors editing the same novel, each with their own full copy of the manuscript. A remote is the shared printer in the hallway — fetch is walking over and reading the latest pages without copying them into your draft, pull is photocopying them into your own binder, and push is dropping your new chapter into the printer's output tray for everyone else to pick up. A merge conflict is what happens when two authors both rewrote page 42 differently: the editor lines the two versions up side by side with the original and asks you to stitch the intent of both into one final page. Force-pushing to a shared branch is yanking everyone else's printed copies out of their hands and replacing them — use --force-with-lease so the printer refuses if someone walked in while you weren't looking.
Remotes
A remote is a named reference to another copy of the repository:
git remote -v # list remotes
git remote add upstream https://... # add a second remote (e.g., the fork's parent)
git fetch origin # download updates from origin without merging
git fetch --all # fetch from all remotes
fetch is safe: it downloads data but changes nothing in your working tree. pull is fetch + merge (or fetch + rebase if configured).
git pull --rebase origin main # fetch then rebase instead of merge
Setting pull.rebase = true in your git config makes this the default, which keeps history linear.
push/pull/fetch
| Command | Effect |
|---|---|
git fetch origin |
Download remote state, no local changes |
git pull |
Fetch + merge (or rebase) current branch |
git push origin feat/x |
Upload local branch to remote |
git push -u origin feat/x |
Upload and set upstream tracking |
git push --force-with-lease |
Force-push but refuse if remote has unexpected commits |
Never use git push --force on a shared branch. It will silently overwrite commits your teammates have pushed. --force-with-lease checks first.
Pull requests
A pull request is not a git concept — it is a code review workflow layered on top of git by hosting platforms. The underlying mechanics:
- Push your branch to origin.
- Open a PR targeting the base branch (usually main).
- CI runs automatically.
- Reviewers read the diff and leave comments.
- You push new commits to address feedback (the PR updates automatically).
- Approval → merge.
A PR is a conversation artifact as much as it is a code diff. The description, comments, and decisions made during review are valuable project history.
Resolving conflicts
A conflict happens when two branches both modified the same region of the same file. Git cannot decide which change to keep, so it marks the conflict in the file:
<<<<<<< HEAD
return user.authenticate(password);
=======
return user.verifyPassword(password, { algorithm: "argon2id" });
>>>>>>> feat/auth-upgrade
<<<<<<< HEAD— your current branch's version=======— separator>>>>>>> feat/auth-upgrade— the incoming branch's version
To resolve:
- Edit the file to the correct final state (remove all conflict markers).
git add <file>to mark it resolved.git merge --continue(orgit rebase --continue).
For complex conflicts, a three-way merge view is essential:
- Base — the common ancestor (what both branches agreed on before diverging)
- Ours — your branch's version
- Theirs — the incoming branch's version
Seeing all three makes the intent of each change obvious. Most editors (VS Code, IntelliJ) show this view automatically when a conflict is detected.
Code review flow
A review isn't just correctness checking. It covers:
- Correctness — does the code do what the description says?
- Edge cases — what happens on nil, empty, zero, overflow?
- Error handling — are errors surfaced or swallowed?
- Tests — do they actually cover the new behaviour?
- Security — any injection, IDOR, path traversal, auth bypass opportunities?
- Performance — N+1 queries, missing indexes, large allocations in hot paths?
- Consistency — does this match the rest of the codebase's conventions?
As an author, make reviews easy:
- Keep PRs small (under 400 lines of diff is a good ceiling)
- Write a clear description explaining why, not just what
- Self-review before requesting review — catch your own obvious mistakes
- Respond to every comment, even if only "done" or "intentional, explained in body"
Stale branches and cleanup
git branch -d feat/done # delete local branch (safe: refuses if unmerged)
git push origin --delete feat/done # delete remote branch
git remote prune origin # remove local references to deleted remote branches
git branch --merged main # list branches fully merged into main
Keep your branch list clean. A long list of stale branches is cognitive overhead.
The conflict playground
The playground below simulates a three-way conflict: two developers (you and a teammate) both edited the same file section. Your task is to resolve the conflict hunk by hunk and produce a valid merge commit.