DevOps Foundations · Module 4: Git and team workflow
Resolving Conflicts
Conflicts are two correct intentions meeting in one file. This lesson resolves them for behavior, with proof, instead of picking sides by seniority.
10 min reading
Objectives
- Read conflict markers and reconstruct both sides' intent
- Resolve for behavior, then prove it with tests, not eyeballing
- Use ours/theirs only when you can state which side is authoritative
- Abort a merge cleanly when the conflict is bigger than expected
Why this matters
Two engineers change the same default: one raises a timeout for a slow dependency, the other lowers it after an incident review. Git stops and asks, and the wrong answer ships whichever change the resolver skimmed last. Most conflict damage is not the markers left in files; it is the silently wrong resolution that passes review because the diff looks tidy. Conflicts demand understanding both sides before touching either.
Concepts
Markers divide the file into three regions: ours (HEAD, your side), theirs (the incoming side), and the base both changed from, visible with merge conflictStyle diff3. Read all three. Ours-versus-theirs tells you what collided; the base tells you what each side intended to change. Two additions in the same spot with different values are a decision, not a merge: somebody must choose, and the choice belongs in the commit message with the reason.
Resolve for behavior, in this order: understand both intents, edit the file to implement the combined intent, remove every marker, then run the relevant tests. Tests are the proof; a conflict resolved without running anything is a guess with good formatting. When the suite covers the collided code, green is evidence. When it does not, write the smallest test that captures the combined behavior before resolving, so the resolution is verified by construction.
git checkout --ours/--theirs (and merge -Xours/-Xtheirs) picks a whole side blindly. Legitimate uses exist: generated files, vendored drops, and cases where one side is definitionally authoritative. The rule is strict: name which side is authoritative and why, in the commit message. Silent -Xtheirs on hand-written code is how a security fix gets reverted by someone who never saw it.
Worked example
Both sides change a retry default. Markers up:
<<<<<<< HEAD MAX_RETRIES = 5 # raised for flaky staging (Aisha) ======= MAX_RETRIES = 2 # lowered after incident review (Bora) >>>>>>> feature/faster-failover
Expected procedure: read the base (was 3), read both reasons (flaky staging versus incident review), and realize these are different environments wanting different values: the resolution is not 5, 2, or 3, but a per-environment setting with staging at 5 and production at 2, committed with both names in the message. A pick of either number would have re-broken someone's week. Lab L10 replays exactly this shape: resolve preserving behavior, with the test proving it.
The common wrong move
Resolving by deleting the other side's lines to make the markers go away. Marker-free files feel done, and reviewers skim them, but the deleted intent (targeted fix, incident learning, customer workaround) returns as a regression with no trail. Every deleted hunk needs a reason stronger than tidiness; when in doubt, stop the merge (git merge --abort), talk to the other author, and resolve together.
Lab and next step
Lab L10 gives you a two-change conflict and requires the behavior-preserving resolution with test proof. Next, lesson 3 handles published mistakes: revert, reset and recovery.
Quick check
An optional 4-question self-check. Answers never leave your device, are not stored, and never count toward any assessment.
Lesson feedback
No published feedback yet.
Log in and complete the lesson to leave feedback.
Exercise
In a scratch repo, create a genuine content conflict between two branches (same line, different values with different reasons). Resolve it, write the reasoning in the commit message, and show the test that proves combined behavior.
Pass criteria
Conflict is genuine (same region, both sides meaningful); resolution implements combined intent, not a side pick; commit message records the reasoning; a test proves the outcome.