Git
How to Resolve Merge Conflicts in Git?
When working in a team or across multiple branches, it’s common to encounter merge conflicts in Git. Merge conflicts occur when changes in two branches interfere with each other, making it impossible for Git to automatically merge them. In this guide, we’ll discuss why conflicts occur, how to handle them, and strategies for preventing them in the future.
What Are Merge Conflicts?
A merge conflict happens when:
- Changes made in one branch overlap or contradict changes in another branch.
- Git cannot automatically reconcile the differences, requiring manual intervention.
Common scenarios where conflicts arise include:
- Multiple developers editing the same line in a file.
- A file being deleted in one branch but modified in another.
- Large refactoring or changes in shared files.
Git will pause the merge process and mark the conflict areas for review, allowing you to decide which changes to keep.
Step 1: Identify the Conflicting Branch
First, understand which branches you’re trying to merge. For example, if you’re working on feature-branch
and want to merge it into main
, start by switching to the target branch:
git checkout main
Then, initiate the merge:
git merge feature-branch
If conflicts occur, Git will stop the merge process and show a message listing the files with conflicts.
Step 2: Check Files with Conflicts
To list all files with conflicts, use:
git status
This command shows:
- Modified files with conflicts.
- Files that still need resolution before the merge can complete.
For instance, you might see output like this:
both modified: app.js
both modified: index.html
These files contain conflicts that need to be resolved.
Step 3: Open the Files with Conflicts
Open each file marked with conflicts. Git highlights the conflicting sections with the following format:
<<<<<<< HEAD
Your changes in the current branch
=======
Changes from the branch being merged
>>>>>>> feature-branch
- The section between
<<<<<<< HEAD
and=======
shows the code in your current branch (e.g.,main
). - The section between
=======
and>>>>>>>
shows the code from the branch you’re merging (e.g.,feature-branch
).
Your task is to decide which version to keep, or if a combination of both is necessary.
Step 4: Resolve the Conflict
To resolve the conflict:
- Keep the Current Branch Changes: If you want to keep only the changes from your current branch, delete the lines marked by
<<<<<<<
,=======
, and>>>>>>>
and retain only your code. - Keep the Incoming Branch Changes: If you prefer the changes from the other branch, delete the lines marked by
<<<<<<<
,=======
, and>>>>>>>
and retain the code from the merged branch. - Combine Both Changes: If you need elements from both branches, edit the code to integrate them as needed, then delete the conflict markers.
For example, resolving a conflict in app.js
might look like this:
Original conflict:
<<<<<<< HEAD
console.log("Hello from main branch");
=======
console.log("Hello from feature branch");
>>>>>>> feature-branch
Resolution (combined change):
console.log("Hello from main branch");
console.log("Hello from feature branch");
Once resolved, save the file.
Step 5: Mark the File as Resolved
After resolving each conflict, you need to mark the files as resolved and stage them for commit. Use the following command to add each resolved file:
git add <file-name>
For instance:
git add app.js index.html
Alternatively, you can use git add .
to add all resolved files.
Step 6: Complete the Merge
Once all conflicts are resolved and the files are staged, complete the merge by committing the changes:
git commit
Git will prompt you with a default message indicating a merge, or you can add your own custom commit message:
git commit -m "Resolved merge conflicts between main and feature-branch"
This command finalizes the merge, and your branch now contains the resolved code.
Step 7: Verify the Merge
After resolving conflicts and committing the changes, it’s good practice to:
- Test Your Code: Run any relevant tests or build processes to confirm that everything works as expected with the merged code.
- Push Changes to the Remote Repository: If this is a shared branch, push the changes to the remote repository so your team can access the merged code:
git push origin main
Advanced Tips for Resolving Merge Conflicts
- Use a Merge Tool:
Git supports several merge tools, likevimdiff
,meld
, orVS Code
, which can make it easier to view and resolve conflicts visually. To open a merge tool, you can use:
git mergetool
This command will open the conflicts in your configured merge tool, where you can resolve them interactively.
- Abort the Merge (If Needed):
If you need to abandon the merge due to excessive conflicts, you can reset to the state before the merge:
git merge --abort
This command cancels the merge process and returns your branch to the state before initiating the merge.
- Automate Conflict Resolution (Use with Caution):
You can usegit checkout --theirs
orgit checkout --ours
to automatically resolve conflicts by choosing one branch’s changes over the other’s. However, this approach should be used cautiously, as it could discard important changes.
git checkout --theirs <file-name>
: Accept changes from the branch being merged.git checkout --ours <file-name>
: Keep the current branch’s changes.
- Keep Commits Small and Focused:
To minimize conflicts, avoid large, unrelated changes in a single commit. Smaller, focused commits are easier to merge and review.
Preventing Merge Conflicts
While conflicts are sometimes unavoidable, there are strategies to reduce their frequency:
- Regularly Pull Changes from the Main Branch:
Periodically pull updates from the main branch into your feature branch to keep your work aligned with the latest changes.
git pull origin main
- Coordinate with Team Members:
Communicate with your team to avoid simultaneous edits to the same parts of a file, especially in complex projects. - Use Feature Branches:
Working in isolated feature branches helps limit changes and makes it easier to merge without conflicts. - Avoid Large Refactoring in Active Code:
Large structural changes increase the chances of conflicts. If you must refactor, communicate with your team and aim to do so when other work is less active.
Conclusion
Merge conflicts are a natural part of collaborative Git workflows, but with the right approach, they can be easily managed. By understanding how to identify, resolve, and prevent conflicts, you’ll be able to navigate complex codebases smoothly and keep projects on track. Regular communication, small commits, and frequent pulls from the main branch can further reduce the chance of conflicts, making collaboration in Git more efficient.