Phase 5: Advanced & Professional Skills

Merge conflict resolution & interactive rebase

Beginner ~3 min read
Think of it this way A friendly analogy. Read this if the technical version feels dense. Show Hide

Imagine you and a few friends are building a super amazing, giant LEGO castle together. It’s too big for one person, so everyone takes a different section or works on adding different cool features.

Now, Git is like a super smart, magical blueprint and planner for your castle. It keeps track of every single brick, every door, every window, and every change each person makes. It’s brilliant because it lets everyone work on their own parts at the same time without accidentally knocking over someone else’s tower or putting a window where a door should be.

But sometimes, even with a smart planner, things can get a little tricky. Let’s say you’re building a fancy tower, and your friend decides to add a flag to the top of that exact same tower at the same time. You wanted a red flag, but your friend thought a blue one would look better. When the magical planner tries to combine your work, it suddenly stops and says, "Whoa! I have two different flags for the exact same spot on the tower! I don't know which one to pick!" This is what grown-ups call a "merge conflict." The planner then puts little sticky notes with question marks all over that tower, showing you both ideas. You and your friend then have to look at the sticky notes and decide together: do we want the red flag, the blue flag, or maybe we can design a new flag that uses both red and blue? Once you tell the planner what to do, it can finish combining everyone’s work.

The planner has another cool trick, too. Before you add your finished tower to the main castle, you might realize you put a window upside down earlier, or maybe you added three tiny pieces one by one when you really meant it as one big step for a wall. The planner lets you go back to your own section and "tidy up" your building steps before showing them to everyone else. You can combine those three tiny pieces into one neat step, or flip that window the right way, making your part of the blueprint super clear and perfect. This tidying up and organizing your own steps is what grown-ups call "interactive rebase."

So, whether it’s helping you solve disagreements about a flag or tidying up your own work to make it super clear, these tools mean you can team up with others to build incredibly complex and awesome things. This means you can collaborate on projects easily, ensuring everyone's contributions fit together smoothly, and that the history of how your amazing castle was built is always neat and easy to understand.

As a Frontend Developer, you'll constantly collaborate with others and manage your codebase using Git. "Merge conflict resolution" and "interactive rebase" are two powerful, yet often intimidating, tools that give you fine-grained control over your project's history. A merge conflict occurs when Git can't automatically combine changes from two different branches into one, usually because the same lines of code in the same file were modified differently by multiple people. For example, if you change the styling of a div in CSS while a teammate renames the entire class in the same div, Git will flag this as a conflict. When this happens, Git pauses the merge, marks the conflicted areas in your files with special markers (<<<<<<<, =======, >>>>>>>), and asks you to manually decide which changes to keep, or how to combine them, before you can finalize the merge.

Key Takeaways

  • Merge conflicts occur when Git can't automatically combine conflicting changes from different branches.
  • To resolve a conflict, you manually edit the conflicted files, choose which changes to keep, and then stage and commit the resolution.
  • Interactive rebase (git rebase -i) allows you to rewrite and clean up your local commit history before sharing it.
  • Use interactive rebase to squash multiple small commits into one, reword commit messages, or reorder commits for a cleaner history.
  • Crucially, never rebase commits that have already been pushed to a shared remote repository, as this can cause significant issues for collaborators.

Code Example

bash
git status
# Output might show:
# Unmerged paths:
#   (use "git add <file>..." to mark resolution)
#   both modified:   src/components/Button.jsx

# --- Example of a conflicted file (src/components/Button.jsx) ---
# <<<<<<< HEAD
# function Button({ children }) {
#   return <button className="btn-primary">{children}</button>;
# }
# =======
# function Button({ label }) {
#   return <button className="btn-secondary">{label}</button>;
# }
# >>>>>>> feature/new-button-design

# --- Manual Resolution: Edit the file to combine or choose changes ---
# function Button({ children, label }) {
#   return <button className="btn-primary-new">{children || label}</button>;
# }

git add src/components/Button.jsx
# Stage the file after manually resolving the conflict

git commit -m "FEAT: Resolve merge conflict in Button component and standardize props"

How this code works

This code demonstrates how to manually resolve a Git merge conflict when Git cannot automatically combine changes from two branches. Initially, git status reveals a conflict, indicating that src/components/Button.jsx has been "both modified." Inside the conflicted file, Git inserts special markers: <<<<<<< HEAD highlights the version from the current branch, ======= acts as a separator, and >>>>>>> feature/new-button-design shows the version from the branch being merged, clearly outlining the sections that need attention.

To resolve the conflict, a developer manually edits the Button.jsx file, removing the conflict markers and combining the desired changes. A common and robust strategy, shown in the "Manual Resolution" example, is to synthesize a new solution rather than just picking one version. Here, the Button component is updated to accept both children and label props, using children || label to provide flexibility. After the file is edited and the conflict markers are removed, git add src/components/Button.jsx stages the resolved file, signaling to Git that the conflict has been handled. Finally, git commit creates a new commit that records the resolution, completing the merge.