Mastering Git Pull Request Conflicts: A Real-World Case Study
The Challenge
I recently faced what appeared to be a complex merge conflict situation in my Rails project. Two pull requests were showing as "CONFLICTING" with the main branch, and I needed to resolve them without losing any valuable code. What I discovered through systematic investigation transformed a seemingly complex problem into a simple solution.
Discovery Process
Initial Investigation
I started by checking the repository state and examining all pull requests:
# Check current branch status
git status
# List all pull requests with their status
gh pr list --repo ltphongssvn/rails-dream-of-code-app --state all --limit 10
This revealed four pull requests, with PR #2 showing a CONFLICTING status.
Analyzing the Conflict
To understand the severity of the conflict, I checked the PR's merge status:
gh pr view 2 --repo ltphongssvn/rails-dream-of-code-app --json state,mergeable,mergeStateStatus
The output confirmed:
{
"mergeStateStatus": "DIRTY",
"mergeable": "CONFLICTING",
"state": "OPEN"
}
The Root Cause Discovery
Through careful investigation, I discovered that the "conflicts" weren't actually conflicts at all. The work from PRs #1 and #2 had already been merged through newer PRs (#3 and #4).
Verification Commands
I verified this by comparing the content:
# Check if lesson files already exist in main
ls -la lesson-02-assignment && wc -l lesson-02-assignment
ls -la lesson-03-assignment && wc -l lesson-03-assignment
# Compare file contents between branches
git diff main:lesson-02-assignment origin/feature/lesson-02-assignment:lesson-02-assignment
The empty diff output confirmed the files were identical.
The Solution: Cherry-Pick Strategy
Finding Unique Commits
I identified commits that weren't yet in main:
git log main..origin/feature/lesson-02-assignment --oneline
This revealed only one valuable commit: adding test_output.txt
to .gitignore
.
Extracting the Valuable Change
# Create a new branch
git checkout -b update-gitignore-test-output
# Cherry-pick the specific commit
git cherry-pick 8934189
# Push the branch
git push -u origin update-gitignore-test-output
Creating and Merging a Clean PR
# Create new PR
gh pr create --repo ltphongssvn/rails-dream-of-code-app \
--base main \
--title "Add test_output.txt to .gitignore" \
--body "Cherry-picked from PR #1."
# Merge the PR
gh pr merge 6 --repo ltphongssvn/rails-dream-of-code-app --merge
Cleanup: Closing Obsolete PRs
With all valuable code preserved, I closed the obsolete PRs with explanatory comments:
gh pr close 1 --repo ltphongssvn/rails-dream-of-code-app \
--comment "Closing as obsolete. Content merged via PR #3. The .gitignore update merged via PR #6."
gh pr close 2 --repo ltphongssvn/rails-dream-of-code-app \
--comment "Closing as obsolete. Content merged via PR #4."
Key Takeaways
- Investigate before acting: What appears as a conflict might be duplicate work already merged.
- Use precise Git commands: Tools like
git diff
andgit log
reveal the true state of your repository. - Cherry-pick strategically: Extract only the commits you need rather than attempting complex merges.
- Document your actions: Always explain why you're closing PRs to maintain clear project history.
Essential Commands Reference
# PR Investigation
gh pr list --state all
gh pr view [PR-NUMBER] --json state,mergeable,mergeStateStatus
# Branch Comparison
git log main..origin/[branch-name] --oneline
git diff main:[file] origin/[branch]:[file]
# Selective Merging
git cherry-pick [commit-hash]
# PR Management
gh pr create --base main --title "Title" --body "Description"
gh pr merge [PR-NUMBER] --merge
gh pr close [PR-NUMBER] --comment "Reason"
Conclusion
This experience taught me that systematic investigation often reveals simpler solutions than initially apparent. By using Git's powerful comparison tools and GitHub's CLI, I transformed what seemed like a complex merge conflict into a simple cherry-pick operation. The result was a cleaner git history and no lost code.
The next time I face PR conflicts again, I will take time to understand what’s already in the main branch before attempting any merges. I might discover that the solution is simpler than the problem appears.
If you enjoyed this article, you can also find it published on LinkedIn and Medium.