Beginner · Git in depth · topic 11 of 53 · 30 min
Branching, merging and conflicts
Explanation
Why branches?
Imagine you are halfway through a new checkout page when an urgent bug is reported in production. Without branches, your half-finished code is mixed with the fix. With branches, the new page lives on its own line of work. You switch to a fresh branch from main, fix the bug, ship it, and come back to your page later. Nothing gets mixed up.
A branch is just a pointer
In Git, a branch is a tiny file that holds the ID of one commit. When you make a new commit on a branch, the branch label moves forward to the new commit. HEAD is another pointer: it says which branch you are on right now. That is why branches cost nothing to create, and why teams create many of them.
git branch # list branches; * marks the current one
git switch -c feature/upi-pay # create a branch and switch to it
# ...edit, add, commit...
git switch main # go back to main
git branch -d feature/upi-pay # delete a branch that is already merged
git branch -D old-experiment # force-delete, even if not merged (careful)If you check out a commit ID instead of a branch name, Git says you are in "detached HEAD" state. You can look around, but new commits there belong to no branch. If you want to keep them, create a branch with git switch -c name before you leave.
Merging: fast-forward
You merge a branch into the branch you are on. If main has had no new commits since you created your feature branch, Git does not need a new commit: it just moves the main label forward to the tip of the feature branch. This is a fast-forward merge, and the history stays a straight line.
Merging: three-way merge
If both branches have new commits, Git finds their common ancestor (the merge base) and combines the changes from both sides since that point. It then creates a merge commit, a commit with two parents. git log --graph draws this as two lines joining.
git switch main
git merge feature/upi-pay
git log --oneline --graph --all
* 7d41c2e Merge branch 'feature/upi-pay'
|\
| * a19f0b3 Add UPI QR payment option
* | 5e2c8d1 Fix delivery charge for pin codes
|/
* 3f9c2ab Add checkout pageMerge conflicts
A conflict happens when both branches changed the same lines of the same file, or one deleted a file the other edited. Git cannot guess which version is right, so it stops and writes both versions into the file between conflict markers.
def delivery_charge(total):
<<<<<<< HEAD
return 0 if total >= 499 else 40
=======
return 0 if total >= 599 else 49
>>>>>>> feature/new-pricing- Run git status to see which files are in conflict ("both modified").
- Open each file and decide the correct result. It may be one side, the other, or a mix. Talk to the person who wrote the other side if unsure.
- Delete all three marker lines.
- Run your tests, then git add the file to mark it resolved.
- Run git commit (or git merge --continue) to finish the merge.
Common mistakes and how to fix them
- Long-lived branches cause big, painful conflicts. Merge small branches often, and bring main into your branch regularly.
- Working on main by accident? Create a branch where you are with git switch -c feature/x; your commits come with you. Then reset main to match the server version.
- Deleted a branch that was not merged? Find its last commit ID in git reflog and create the branch again.
Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
Branching, merging and conflicts · 1/8
Branches let you work on several things at once without mixing them up.
Prefer a video by a teacher? Find free videos on “git branching merging merge conflict tutorial” on YouTube ↗
In real life: Two developers on a grocery delivery app in Hyderabad
Ravi changes the free-delivery limit from 499 to 599 rupees on a pricing branch. On another branch, Meena changes the delivery fee from 40 to 49 rupees in the same line. Meena merges first. When Ravi merges main into his branch, Git shows a conflict in pricing.py. Ravi checks with the product manager, keeps the 599 limit and the 49 fee, removes the markers, runs the tests, and commits the merge. The pull request now shows one clean, agreed change.
git switch feature/new-pricing
git merge main # CONFLICT (content): Merge conflict in pricing.py
# edit pricing.py, remove the markers
git add pricing.py
git commit # finishes the mergePractice (0/3 done)
What does git switch -c feature/login do?
A merge can be a fast-forward only if the current branch tip is an ANCESTOR of the other branch tip (it is reachable by following parent links backwards). Write can_fast_forward(parents, current, other). parents is a dict mapping each commit ID to a list of its parent IDs (the first commit has an empty list). Return True if current can be reached from other by following parents, or if they are the same commit.
Write split_conflict(text) that takes a file with merge conflict markers and returns a tuple (ours, theirs): the whole file as it would be if you kept only your side, and as it would be with only their side. Lines outside a conflict go into both. A line starting with "<<<<<<<" begins our side, "=======" switches to their side, and ">>>>>>>" ends the conflict. Marker lines are never copied. Join the lines with "\n".
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Rebase, undo and rescue: rebase, reset, revert, reflog and stashGit in depth · same module
- Collaboration: remotes, pull requests and branching strategiesGit in depth · same module
- Git and GitHubFrontend Web Development · Async JavaScript, modules and tools
- Two pointersData Structures and Algorithms (DSA) for interviews · Hashing, two pointers and sliding window
- Fast and slow pointers and merging listsData Structures and Algorithms (DSA) for interviews · Stacks, queues and linked lists
- Upserts: insert or updateSQL and Databases · Changing data, transactions and ACID
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
In Git, what is a branch?
Answer: A movable pointer to a commit
A branch is a small reference holding one commit ID. It moves forward when you commit.
main has no new commits since feature was created. What does git merge feature (run on main) do by default?
Answer: Moves main forward to the tip of feature (fast-forward)
When main is an ancestor of feature, Git just moves the pointer. Use --no-ff if you want a merge commit anyway.
In a conflicted file, which part is between ======= and >>>>>>> feature?
Answer: The version from the branch being merged in (theirs)
Our side (HEAD) is first; the incoming branch's version comes after =======.
You fixed all conflicts in two files. What is the next step?
Answer: git add the files, then git commit
Staging the files marks them resolved; the commit completes the merge. --abort would throw your work away.
What is "detached HEAD"?
Answer: HEAD points directly at a commit instead of a branch
New commits made there belong to no branch. Create one with git switch -c name to keep them.
What does git switch -c feature/cart do?Related
Answer: Creates a branch called feature/cart and moves you to it
-c means create. switch moves you to that branch so your new commits go there.
From Git and GitHub
In trunk-based development, how do teams merge unfinished features safely?Related
Answer: They hide unfinished work behind feature flags
Feature flags let half-built code be merged and deployed while switched off, so branches stay short-lived.
From Collaboration: remotes, pull requests and branching strategies
You ran git add on a file. Which command shows the changes that will go into the next commit?Related
Answer: git diff --staged
git diff --staged compares the staging area with the last commit. Plain git diff shows only unstaged changes.
You need one bug-fix commit from main in the release/3.1 branch, and nothing else. Which command fits?Related
Answer: git cherry-pick <fix-commit-id>
cherry-pick applies just that commit's changes as a new commit on the current branch.
From Rebase, undo and rescue: rebase, reset, revert, reflog and stash
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- 3 more topics in “Git in depth” before its exam: Rebase, undo and rescue: rebase, reset, revert, reflog and stash, Collaboration: remotes, pull requests and branching strategies, Semantic versioning, tags and releases.
- Module 3 exam: Git in depth · 13 questions · 25 min, without help. 5 topics of this module still to finish first.
- Then the next module, Docker. 53 topics left in the course before the final exam.