P-2.4 Working With Other People on Code
Git collaboration as documented in Pro Git — written September 2026
What this is and why it exists
Working alone, version control is an undo button. Working with other people, it becomes the mechanism by which several changes to the same files stop destroying each other.
That is a different job, and it needs a few more ideas. Separate lines of development. Merging. Conflicts. Review.
One of those is misunderstood almost universally, so let us settle it now. A conflict is not an error, and it is not the tool failing. It is the tool refusing to guess which of two intentions you meant.
The vocabulary
- Branch — a movable name for a line of commits. Starting one costs nothing.
- Merge — bringing two lines of work back together.
- Merge commit — the commit that results, with two parents rather than one.
- Conflict — a place where two people changed the same lines.
- Remote — a shared copy of the repository that yours exchanges commits with.
- Diverged — your copy and the shared copy each have commits the other lacks.
- Review — a conversation about a proposed change before it joins the shared history.
The mental model
Start work on a separate line, always. A branch is only a movable name pointing at a line of commits, so creating one costs nothing at all. What it buys is that unfinished work stays away from the version everyone else is using. Nearly every team convention you will meet is built on that single idea.
When the work is done, the two lines come back together. The merge produces a commit with two parents, and being able to see that in the history is how anyone reconstructs what happened months later.
Sometimes the merge stops and asks. That is a conflict, and it means two people changed the same lines. The tool could pick one. It deliberately does not, because picking would silently discard somebody's intention. The work is to read both versions and decide on purpose. Choosing one at random is exactly how correct code disappears without anyone noticing.
Remotes are the next idea, and one sentence removes most of the fear around them. Your copy and the shared copy are two separate repositories that exchange commits. That is why a push can be refused: the shared copy has moved on, and the two histories have diverged. Nothing is broken. You are being told to reconcile before you overwrite.
Finally, review. A review is a conversation about a proposed change before it becomes part of the shared history. Being useful in one means reading for correctness first. Does this do what it says? Does it handle the empty case? Does it break anything else? Taste comes a long way second. Reviews that lead with taste teach people to dread them.
What you should now be able to explain or do
Start work on a separate line as a matter of habit, and say why it costs nothing. Merge it back and read what the merge did. Resolve a conflict by reading both sides and deciding deliberately. Explain why a push is refused and what diverged means. Open a change for review, and review someone else's for correctness before taste.
Check yourself
Why is starting a separate line of development the default habit?
It costs nothing, and it keeps unfinished work away from the version other people are using.
Is a conflict a failure of the tool?
No. It is the tool declining to guess between two intentions. Guessing would silently discard one of them.
What is the actual work of resolving a conflict?
Reading both versions and deciding on purpose. Picking one at random is how correct code quietly disappears.
Why can a push be refused?
Because your copy and the shared copy are separate repositories, and the shared one has commits yours does not. The histories diverged.
What should a review lead with?
Correctness. Does it do what it says, does it handle the edge cases, does it break anything else. Taste comes a long way second.
Go deeper
Back to Working With Other People on Code: work through the checklist