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
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.