Resolving Git Merge Conflicts: Manual HEAD Branch Changes on CentOS Stream / Rocky Linux
Master Git merge conflicts by manually resolving HEAD branch changes on CentOS Stream & Rocky Linux. This guide covers common scenarios and step-by-step solutions.
Master Git merge conflicts by manually resolving HEAD branch changes on CentOS Stream & Rocky Linux. This guide covers common scenarios and step-by-step solutions.
Introduction
As a seasoned DevOps engineer or Systems Administrator managing web applications and infrastructure, you've inevitably encountered the dreaded "Git merge conflict." This guide focuses on a specific, yet common, scenario: manually resolving conflicts where changes from your current (HEAD) branch clash with incoming changes during a merge operation on CentOS Stream or Rocky Linux environments.
Merge conflicts arise when Git's automated merging algorithm cannot determine how to integrate divergent changes from two different branches into the same portion of a file. While Git handles simple merges gracefully, simultaneous modifications to the same lines of code, or one branch deleting a file that another modified, will halt the merge process, requiring your expert intervention. Understanding how to manually dissect and reconcile these differences, especially concerning your HEAD branch's contributions, is a fundamental skill for maintaining code integrity and ensuring smooth CI/CD pipelines.
Symptom & Error Signature
When a merge conflict occurs, Git will typically stop the merge process, leaving your working directory in a "merging" state. You'll observe messages similar to these in your terminal, and your files will be marked with special conflict indicators.
# Attempting a merge
$ git merge develop
# Output indicating conflicts
Auto-merging src/main.js
CONFLICT (content): Merge conflict in src/main.js
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.
# Checking the status
$ git status
On branch main
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abandon the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: README.md
both modified: src/main.js
Inside the conflicted files, you'll find special markers delineating the conflicting sections:
// Example of a conflicted file (src/main.js)
<<<<<<< HEAD
console.log("Feature A is active for main branch.");
const appVersion = "1.0.1-beta";
=======
console.log("New UI feature enabled.");
const appVersion = "1.0.0-final";
>>>>>>> feature/new-ui
In this example:
<<<<<<< HEAD: Marks the beginning of the changes from your current branch (mainin this context).=======: Serves as a separator between the two conflicting sets of changes.>>>>>>> feature/new-ui: Marks the end of the changes from the branch you are merging (feature/new-ui).
Root Cause Analysis
Git merge conflicts fundamentally occur because two branches have modified the same lines in the same file(s), or one branch has deleted a file that the other has modified. When Git attempts to combine the history of these branches, it identifies these overlapping changes as ambiguous and pauses for human resolution.
Specifically, when you see:
<<<<<<< HEAD: This section represents the state of the code as it exists in your current working branch (the branch you are merging into). Git refers to this as "our" changes. These are the modifications you (or your team members on this branch) have made.>>>>>>> branch_name_or_commit_hash: This section represents the state of the code from the other branch you are attempting to merge from. Git refers to these as "their" changes. These are the modifications introduced by the incoming branch.
The root cause is a divergence in parallel development:
- Concurrent Modifications: Two developers, or different feature branches, independently modified the exact same lines of code or nearby lines that Git cannot intelligently combine.
- Deletion vs. Modification: One branch deleted a file while the other modified it.
- Renaming Conflicts: A file was renamed in one branch and modified in another, or renamed differently in both.
- Lack of Frequent Integration: Infrequent merges between long-lived branches increase the likelihood and complexity of conflicts.
Understanding that HEAD always refers to your current branch's state is crucial for deciding which changes to keep, discard, or combine during manual resolution.
Step-by-Step Resolution
Resolving merge conflicts is a meticulous process that requires careful attention to detail. Follow these steps to systematically resolve HEAD branch changes on your CentOS Stream or Rocky Linux workstation.
#### 1. Identify the Conflict Status
First, ensure you are in the correct repository and understand the state of the merge.
# Navigate to your Git repository
cd /var/www/my-application
# Check the current status
git status
The output will clearly list the files with conflicts under "Unmerged paths."
On branch main
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abandon the merge)
Changes to be committed:
new file: LICENSE
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: README.md
both modified: src/main.js
#### 2. Locate and Analyze Conflicted Files
Use your preferred text editor (like vim or nano) to open each file listed under "Unmerged paths."
nano README.md
# OR
vim src/main.js
Inside each file, you will find the conflict markers. For example:
<!DOCTYPE html>
<html>
<head>
<title>My Web App</title>
</head>
<body>
<h1>Welcome</h1>
<<<<<<< HEAD
<p>This is the latest content from our main branch.</p>
<p>Version: 1.2.0</p>
=======
<p>Explore the new features added by the develop branch.</p>
<p>Build: 2026-10-27</p>
>>>>>>> develop
</body>
</html>
Here:
- The lines between
<<<<<<< HEADand=======are from your current branch (main). - The lines between
=======and>>>>>>> developare from thedevelopbranch being merged.
#### 3. Edit the Conflicted Files Manually
This is the most critical step. You must manually edit each conflicted section to reflect the desired final state. This involves:
- Deciding which lines to keep: You might keep your
HEADchanges, the incoming changes, or a combination of both. - Removing all conflict markers: (
<<<<<<< HEAD,=======,>>>>>>> branch_name). - Ensuring the resulting code is syntactically correct and logically sound.
Example Resolution:
Let's resolve the src/main.js example from earlier:
// Original conflicted content
<<<<<<< HEAD
console.log("Feature A is active for main branch.");
const appVersion = "1.0.1-beta";
=======
console.log("New UI feature enabled.");
const appVersion = "1.0.0-final";
>>>>>>> feature/new-ui
If you decide to keep the HEAD's console.log message but take the incoming appVersion because it's newer, and then add a new combined message:
// Resolved content
console.log("Feature A is active for main branch.");
console.log("Combined message: UI features are being integrated.");
const appVersion = "1.0.0-final"; // Keeping the incoming appVersion
Always thoroughly review the code you've produced during a manual conflict resolution. A single missed marker or a logically incorrect combination of code can introduce subtle bugs that are hard to trace later. If possible, consult with team members who made the conflicting changes.
Repeat this process for all conflicted files.
#### 4. Stage the Resolved Files
After you have manually edited a file and removed all conflict markers, you must tell Git that the file has been resolved and is ready to be committed.
git add README.md
git add src/main.js
# ... do this for all conflicted files
You can verify that files are staged correctly using git status again:
$ git status
On branch main
All conflicts fixed but you are still merging.
(use "git commit" to conclude merge)
Changes to be committed:
new file: LICENSE
modified: README.md
modified: src/main.js
#### 5. Complete the Merge Commit
Once all conflicts are resolved and staged, you can finalize the merge by creating a new commit.
git commit
This command will open your default text editor (e.g., vim, nano) with a pre-filled merge commit message.
Merge branch 'develop'
# Conflicts:
# README.md
# src/main.js
#
# It looks like you may be committing a merge.
# If this is not correct, please remove the file
# .git/MERGE_MSG
# and try again.
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch main
# All conflicts fixed but you are still merging.
#
# Changes to be committed:
# new file: LICENSE
# modified: README.md
# modified: src/main.js
#
You can accept the default message or modify it to add more context about how the conflicts were resolved. Save and close the editor to complete the merge commit.
#### 6. Verify Resolution and Clean Up
After the commit, verify that your repository is in a clean state and the merge was successful.
git status
You should see:
On branch main
Your branch is ahead of 'origin/main' by 1 commit.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
You can also inspect the commit history to confirm the merge:
git log --oneline --graph --all
If you realize you've made a mistake or wish to abandon the merge process at any point before completing the
git commit, you can revert to the state before the merge attempt:git merge --abortThis will discard any manual resolutions and return your branch to its original state.
#### 7. Advanced Tools and Scenarios
For complex conflicts, git mergetool can be invaluable. It launches a graphical diff/merge tool to guide you through the resolution process.
Configure git mergetool
First, ensure you have a mergetool installed (e.g., meld, kdiff3, VS Code, Beyond Compare). On CentOS Stream/Rocky Linux, you might install meld:
sudo dnf install meld -y
Then, configure Git to use it:
git config --global merge.tool meld
git config --global mergetool.prompt false # Automatically launch the tool
Using git mergetool
When conflicts arise, instead of manually editing:
git mergetool
This will launch your configured mergetool for each conflicted file, presenting three or four panes: your changes (LOCAL), their changes (REMOTE), the common ancestor (BASE), and the final merged result.
Resolving "Deleted by Us" / "Deleted by Them"
Sometimes conflicts involve deletions:
deleted by us: You deleted the file, but the incoming branch modified it. Git prompts you to decide: keep the deletion (git rm <file>) or restore the file with their changes (git add <file>).deleted by them: They deleted the file, but you modified it. Similar decision: keep your modified file (git add <file>) or accept their deletion (git rm <file>).
In these cases, git status will show:
Unmerged paths:
(use "git add/rm <file>..." as appropriate to mark resolution)
deleted by us: config/settings.yml
deleted by them: assets/icon.png
To resolve config/settings.yml (deleted by us, modified by them), if you want to keep their modifications:
# Checkout their version to restore the file, then add it
git checkout --ours config/settings.yml # Reverts to the state in our branch (which deleted it)
# Oops, that was wrong. --ours refers to HEAD.
# To keep *their* changes (the incoming branch) for a file deleted by *us*:
git checkout --theirs config/settings.yml
git add config/settings.yml
To resolve assets/icon.png (deleted by them, modified by us), if you want to accept their deletion:
git rm assets/icon.png
git checkout --ours <file>selects the version from your current (HEAD) branch.git checkout --theirs <file>selects the version from the branch you are merging from. Use these with caution and alwaysgit addthe file afterward to mark it as resolved.
By mastering these steps, you can confidently navigate and resolve even the most challenging Git merge conflicts, ensuring the stability and continuity of your development and deployment workflows on CentOS Stream and Rocky Linux.
Our Production Verification Guarantee
Encountering a bug not covered here or running a non-standard kernel configuration? Our solutions are continually refined against real production incidents. Submit an environment trace for our editorial team to replicate.