Mastering Git Pull Request Conflicts: A Real-World Case Study

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

  1. Investigate before acting: What appears as a conflict might be duplicate work already merged.
  2. Use precise Git commands: Tools like git diff and git log reveal the true state of your repository.
  3. Cherry-pick strategically: Extract only the commits you need rather than attempting complex merges.
  4. 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.