Skip to main content

Command Palette

Search for a command to run...

Day 33: Git Push Conflicts - Resolving Remote Conflicts 🔀

Published
32 min read
Day 33: Git Push Conflicts - Resolving Remote Conflicts 🔀

Welcome back! 👋 Day 33 of the 100 Days Cloud DevOps Challenge, and today we're mastering Git push conflicts - resolving diverged histories! This is how professionals handle the common "push rejected" error and synchronize with remote changes. Let's resolve conflicts like a pro! 🎯

🎯 The Mission - Fix Push Issues and File Corrections

It's Tuesday morning, and Max is blocked trying to push his changes:

📋 TASK TICKET #DEV-7113 - Resolve Git Push Conflicts
Priority: HIGH
Type: Git Conflict Resolution - Push Issues

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
PROJECT: Story Blog Repository
Team: Sarah & Max - Story Writers
Issue: Push rejected - conflicts with remote
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

BACKGROUND:
└─ Sarah and Max collaborate on story repository
└─ Both push stories independently
└─ Max made local changes
└─ Push is failing (remote diverged)
└─ Need to resolve and sync

SITUATION:
└─ Max: Local changes ready to push
└─ Sarah: Already pushed her changes
└─ Remote: Has Sarah's updates
└─ Local: Has Max's updates
└─ Histories diverged!

REQUIREMENTS:

1. Access Max's Repository:
   └─ Server: Storage Server (ststor01)
   └─ User: max (password: Max_pass123)
   └─ Location: /home/max/story-blog
   └─ Action: SSH and navigate

2. Identify Push Problem:
   └─ Attempt to push
   └─ Understand rejection reason
   └─ Analyze divergence
   └─ Check remote state

3. Fix story-index.txt:
   └─ Must have titles for ALL 4 stories
   └─ Ensure complete index
   └─ Proper formatting

4. Fix Typo:
   └─ File: Contains "The Lion and the Mooose"
   └─ Typo: "Mooose" (3 o's) 
   └─ Correct: "Mouse" 
   └─ Find and fix

5. Resolve Conflicts:
   └─ Pull remote changes
   └─ Merge Sarah's work with Max's
   └─ Resolve any conflicts
   └─ Maintain both contributions

6. Push Successfully:
   └─ Push merged changes
   └─ Verify on Gitea UI
   └─ Confirm all 4 stories
   └─ Check typo fixed

7. Documentation:
   └─ Take screenshots of Gitea UI
   └─ Show before/after states
   └─ Document resolution steps

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
GITEA ACCESS:
└─ UI: Click "Gitea UI" button
└─ Login: sarah / Sarah_pass123 OR max / Max_pass123
└─ Verify: Repository state and changes
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
STATUS: URGENT - Max blocked, cannot push
DEADLINE: Today
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

This is real-world collaboration! Push conflicts happen when remote changes while you're working locally! 🤝

🤔 Why Push Conflicts Matter - The Collaboration Challenge

The Problem: Diverged Histories

Scenario: Two developers working simultaneously

What Happened:

Monday 9am: Max clones repository
State: A  B  C

Monday 10am: Max works locally
Max's repo: A  B  C  M1  M2
(Not pushed yet)

Monday 11am: Sarah works and pushes
Sarah's repo: A  B  C  S1  S2
Remote: A  B  C  S1  S2 

Monday 12pm: Max tries to push
Max's local: A  B  C  M1  M2
Remote now:  A  B  C  S1  S2

CONFLICT! Histories diverged at C!

The Error Message:

git push origin master

To https://git-server/story-blog.git
 ! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs to 'story-blog.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.

Real stat: 89% of developers encounter push conflicts when collaborating - it's the #1 Git error! 📊

Understanding the Conflict

Why Git Rejects the Push:

Remote (origin/master):
A  B  C  S1  S2
            
      last common commit

Max's Local (master):
A  B  C  M1  M2
            
      last common commit

Problem:
- Both branches have commits after C
- Remote has S1, S2 (Sarah's work)
- Local has M1, M2 (Max's work)
- Git can't automatically merge
- Risk of overwriting Sarah's work!

Git Protection:
 Prevents force push (would delete Sarah's work)
 Requires explicit merge or rebase
 Ensures no work is lost

The Solution: Pull, Merge, Push

Proper Workflow:

Step 1: Pull Remote Changes
git pull origin master
└─ Fetches S1, S2
└─ Merges into local
└─ Creates merge commit

After Pull:
     M1  M2  Merge
    /         /
A  B  C  S1  S2

Step 2: Resolve Conflicts (if any)
- Edit conflicted files
- Choose correct version
- Stage resolved files
- Complete merge

Step 3: Push Merged Result
git push origin master
└─ Now includes both works
└─ Sarah's changes preserved
└─ Max's changes added

Remote After:
     M1  M2  Merge
    /         /
A  B  C  S1  S2

Key insight: Git pull = git fetch + git merge, bringing remote changes and merging automatically!

Real-World Collaboration Scenarios

Scenario 1: The Common Case (Our Situation)

Team: 2 developers, same repository
Timeline:
- Morning: Both pull latest
- Day: Work independently
- Afternoon: One pushes (succeeds)
- Later: Other pushes (rejected!)
Solution: Pull, merge, push

Scenario 2: The Sprint Finish

Friday 4pm: Everyone rushing to push before weekend
Multiple developers: All trying to push simultaneously
First push: Succeeds
All others: Rejected!
Solution: Each pulls, merges, pushes (queue forms)

Scenario 3: The Long-Running Branch

Developer: Working on feature for 3 days
Main branch: 20 commits ahead
Push: Rejected (way behind)
Solution: Pull (big merge), resolve conflicts, push

🏗️ Understanding the Setup

Initial State:

Storage Server (ststor01)

Max's Local Repository:
/home/max/story-blog/
├─ story-index.txt (needs 4 story titles)
├─ story1.txt (Lion and Mouse - has typo "Mooose")
├─ story2.txt
├─ story3.txt
└─ story4.txt

Max's Local Commits:
A  B  C  M1  M2 (master)
            
    Last pulled from remote

Remote (Gitea):
A  B  C  S1  S2 (master)
            
    Sarah's commits

Divergence:
- Local has M1, M2 (Max's changes)
- Remote has S1, S2 (Sarah's changes)
- Common ancestor: C
- Push will fail!

Issues to Fix:
1. Push conflict (diverged histories)
2. story-index.txt incomplete (missing title(s))
3. Typo: "Mooose"  should be "Mouse"

After Our Work:

Max's Local Repository:
/home/max/story-blog/
├─ story-index.txt  (all 4 titles present)
├─ story1.txt  (typo fixed: "Mouse")
├─ story2.txt
├─ story3.txt
└─ story4.txt

Local Commits:
         M1  M2  Merge
        /         /
A  B  C  S1  S2

Remote (Gitea):
         M1  M2  Merge
        /         /
A  B  C  S1  S2

Result:
 Histories merged
 Both Sarah's and Max's work preserved
 Index complete with 4 stories
 Typo corrected
 Push successful
 Remote synchronized

Visual Representation:

BEFORE (Diverged):
━━━━━━━━━━━━━━━━━━━━━━━━━━━
Max's Local:
A  B  C  M1  M2 (HEAD)

Remote:
A  B  C  S1  S2
            
        Sarah pushed

Attempt: git push
Result:  REJECTED!

AFTER PULL & MERGE:
━━━━━━━━━━━━━━━━━━━━━━━━━━━
Max's Local:
     M1  M2  M (merge commit)
    /         /
A  B  C  S1  S2

Attempt: git push
Result:  SUCCESS!

Remote After:
     M1  M2  M
    /         /
A  B  C  S1  S2

🛠️ Complete Step-by-Step Implementation

Phase 1: Access Max's Repository

Step 1.1: SSH as Max

# Connect to storage server as max
ssh max@ststor01
# Password: Max_pass123

You're logged in as Max!

Step 1.2: Navigate to Repository

# Change to story-blog directory
cd /home/max/story-blog

Verify location:

pwd

Output: /home/max/story-blog

Step 1.3: Check Repository Status

# View current status
git status

Expected output:

On branch master
Your branch is ahead of 'origin/master' by 2 commits.
  (use "git push" to publish your local commits)

nothing to commit, working tree clean

Max is ahead by 2 commits!

Step 1.4: View Local Commits

# See Max's local commits
git log --oneline -5

Expected output (example):

m2a3b4c (HEAD -> master) Max: Add story 4
m1a2b3c Max: Update story index
c3d4e5f Previous commit
s2a1b2c Sarah: Add story 3
s1a2b3c Sarah: Update story 2

Max has 2 commits!

Phase 2: Attempt Push and Understand Failure

Step 2.1: Try to Push

# Attempt to push Max's changes
git push origin master

Expected output:

To /opt/story-blog.git
 ! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs to '/opt/story-blog.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

Push rejected! This is expected! ✅

Why it failed:

  • Remote has changes Max doesn't have

  • Git prevents overwriting

  • Need to pull first

Step 2.2: Check Remote State

# Fetch latest remote information
git fetch origin

Expected output:

remote: Counting objects: 5, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 5 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (5/5), done.
From /opt/story-blog
   c3d4e5f..s2a1b2c  master     -> origin/master

Remote updated!

Step 2.3: View Remote Commits

# See what's on remote that we don't have
git log origin/master --oneline -5

Expected output:

s2a1b2c (origin/master) Sarah: Add story details
s1a2b3c Sarah: Update formatting
c3d4e5f Previous commit

Sarah has 2 commits on remote!

Step 2.4: Visualize Divergence

# See branch divergence
git log --oneline --graph --all --decorate

Expected output:

* m2a3b4c (HEAD -> master) Max: Add story 4
* m1a2b3c Max: Update story index
| * s2a1b2c (origin/master) Sarah: Add story details
| * s1a2b3c Sarah: Update formatting
|/
* c3d4e5f Previous commit

Branches clearly diverged!

Phase 3: Examine and Fix Local Files

Step 3.1: Check story-index.txt

# View story index
cat story-index.txt

Expected output (might be missing entries):

Story Index
===========

1. The Lion and the Mouse
2. The Tortoise and the Hare
3. The Fox and the Grapes

Only 3 stories listed! Need to add #4! ❌

Step 3.2: Find the Typo

# Search for "Mooose" (typo)
grep -r "Mooose" .

Expected output:

./story1.txt:Title: The Lion and the Mooose

Found typo in story1.txt!

Step 3.3: View story1.txt

# Check the file with typo
cat story1.txt

Expected output:

Title: The Lion and the Mooose

Once upon a time, a lion caught a mouse...

"Mooose" needs to be "Mouse"!

Step 3.4: Check All Story Files

# List all story files
ls -la *.txt

Expected output:

-rw-r--r-- 1 max max  234 Dec 07 10:00 story-index.txt
-rw-r--r-- 1 max max  456 Dec 07 10:00 story1.txt
-rw-r--r-- 1 max max  378 Dec 07 10:00 story2.txt
-rw-r--r-- 1 max max  290 Dec 07 10:00 story3.txt
-rw-r--r-- 1 max max  412 Dec 07 10:00 story4.txt

All 4 story files exist!

Phase 4: Fix Issues in Local Files

Step 4.1: Fix Typo in story1.txt

# Fix "Mooose" to "Mouse"
sed -i 's/Mooose/Mouse/g' story1.txt

Verify fix:

grep "Mouse" story1.txt

Expected output:

Title: The Lion and the Mouse

Typo fixed!

Step 4.2: Get Story 4 Title

# Check story4.txt to get its title
head -3 story4.txt

Expected output (example):

Title: The Ant and the Grasshopper

In a field one summer's day...

Story 4 title identified!

Step 4.3: Update story-index.txt

# Add missing story 4 to index
nano story-index.txt

Edit to include all 4 stories:

Story Index
===========

1. The Lion and the Mouse
2. The Tortoise and the Hare
3. The Fox and the Grapes
4. The Ant and the Grasshopper

Save and exit (Ctrl+O, Enter, Ctrl+X)

Verify:

cat story-index.txt

All 4 stories now listed!

Step 4.4: Stage Corrections

# Stage the fixed files
git add story1.txt story-index.txt

Check status:

git status

Expected output:

On branch master
Your branch is ahead of 'origin/master' by 2 commits.

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   story-index.txt
        modified:   story1.txt

Fixes staged!

Step 4.5: Commit Corrections

# Commit the fixes
git commit -m "Fix typo: Mooose -> Mouse, complete story index with all 4 titles"

Expected output:

[master n3o4p5q] Fix typo: Mooose -> Mouse, complete story index with all 4 titles
 2 files changed, 3 insertions(+), 1 deletion(-)

Fixes committed!

Phase 5: Pull Remote Changes

Step 5.1: Pull from Origin

# Pull Sarah's changes from remote
git pull origin master

Expected output (if no conflicts):

From /opt/story-blog
 * branch            master     -> FETCH_HEAD
Merge made by the 'recursive' strategy.
 story2.txt | 5 ++++-
 story3.txt | 3 +++
 2 files changed, 7 insertions(+), 1 deletion(-)

Pull successful! 🎉

What happened:

  • ✅ Fetched Sarah's commits (S1, S2)

  • ✅ Merged with Max's commits (M1, M2, M3)

  • ✅ Created merge commit automatically

  • ✅ Both works preserved

Step 5.2: If Conflicts Occur (Alternative Path)

If git pull shows conflicts:

git pull origin master

# Output:
Auto-merging story-index.txt
CONFLICT (content): Merge conflict in story-index.txt
Automatic merge failed; fix conflicts and then commit the result.

Conflict resolution:

# Step 1: Check conflicted files
git status

# Shows:
# Unmerged paths:
#   both modified:   story-index.txt

# Step 2: Edit conflicted file
nano story-index.txt

# Look for conflict markers:
<<<<<<< HEAD (Max's version)
1. The Lion and the Mouse
2. The Tortoise and the Hare
3. The Fox and the Grapes
4. The Ant and the Grasshopper
=======
1. The Lion and the Mouse
2. The Tortoise and the Hare
3. The Fox and the Grapes
3. The Boy Who Cried Wolf
>>>>>>> origin/master (Sarah's version)

# Step 3: Resolve conflict
# Remove markers, merge both lists
# Keep all unique stories

# Step 4: Stage resolved file
git add story-index.txt

# Step 5: Complete merge
git commit -m "Merge remote changes, resolve index conflicts"

For our task: Assume clean merge! ✅

Phase 6: Verify Merge Success

Step 6.1: Check New Commit History

# View commit history after merge
git log --oneline --graph -7

Expected output:

*   p6q7r8s (HEAD -> master) Merge branch 'master' of /opt/story-blog
|\  
| * s2a1b2c (origin/master) Sarah: Add story details
| * s1a2b3c Sarah: Update formatting
* | n3o4p5q Fix typo and complete index
* | m2a3b4c Max: Add story 4
* | m1a2b3c Max: Update story index
|/  
* c3d4e5f Previous commit

Merge commit created!

Step 6.2: Verify All Files Present

# List all files
ls -la *.txt

All 4 story files + index present!

Step 6.3: Verify Index Complete

# Check story index has all 4 titles
cat story-index.txt

Expected:

Story Index
===========

1. The Lion and the Mouse
2. The Tortoise and the Hare
3. The Fox and the Grapes
4. The Ant and the Grasshopper

All 4 stories indexed!

Step 6.4: Verify Typo Fixed

# Confirm typo corrected
grep -i "mouse" story1.txt

Expected output:

Title: The Lion and the Mouse

Typo fixed (Mouse, not Mooose)!

Phase 7: Push Merged Changes

Step 7.1: Check Status Before Push

# Verify ready to push
git status

Expected output:

On branch master
Your branch is ahead of 'origin/master' by 4 commits.
  (use "git push" to publish your local commits)

nothing to commit, working tree clean

Ready to push!

Step 7.2: Push to Origin

# Push merged changes
git push origin master

Expected output:

Counting objects: 12, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (8/8), done.
Writing objects: 100% (12/12), 1.23 KiB | 1.23 MiB/s, done.
Total 12 (delta 3), reused 0 (delta 0)
To /opt/story-blog.git
   s2a1b2c..p6q7r8s  master -> master

Push successful! 🎊

Step 7.3: Verify Remote Updated

# Check remote now matches local
git log origin/master --oneline -3

Expected output:

p6q7r8s (HEAD -> master, origin/master) Merge branch 'master'
n3o4p5q Fix typo and complete index
s2a1b2c Sarah: Add story details

Remote synchronized!

Phase 8: Verify on Gitea UI

Step 8.1: Access Gitea

From browser:

  1. Click "Gitea UI" button on top bar

  2. Gitea login page appears

Login page visible! ✅ 📸 Screenshot 1: Gitea Login Page

Step 8.2: Login as Max

Enter credentials:

  • Username: max

  • Password: Max_pass123

Click "Sign In"

Logged in successfully! ✅ 📸 Screenshot 2: Max's Dashboard

Step 8.3: Navigate to Repository

Steps:

  1. Click on "story-blog" repository

  2. Repository page loads

Repository visible! ✅ 📸 Screenshot 3: Repository Home

Step 8.4: View Commit History

Click on "Commits" tab

Should show:

  • Merge commit (latest)

  • Max's commits

  • Sarah's commits

  • All integrated

📸 Screenshot 4: Commit History

Step 8.5: Verify story-index.txt

Steps:

  1. Click on "story-index.txt" file

  2. View contents

Should display:

Story Index
===========

1. The Lion and the Mouse
2. The Tortoise and the Hare
3. The Fox and the Grapes
4. The Ant and the Grasshopper

All 4 stories listed! ✅ 📸 Screenshot 5: story-index.txt with 4 titles

Step 8.6: Verify Typo Fixed in story1.txt

Steps:

  1. Click on "story1.txt" file

  2. View title

Should show:

Title: The Lion and the Mouse

NOT "Mooose"!

Typo fixed in remote! ✅ 📸 Screenshot 6: story1.txt showing "Mouse"

Step 8.7: Verify All 4 Story Files

In repository file list:

  • ✅ story-index.txt

  • ✅ story1.txt (Lion and Mouse)

  • ✅ story2.txt (Tortoise and Hare)

  • ✅ story3.txt (Fox and Grapes)

  • ✅ story4.txt (Ant and Grasshopper)

All files present! ✅ 📸 Screenshot 7: Repository file list

Step 8.8: Optional - Login as Sarah to Verify

Logout from Max, login as Sarah:

  • Username: sarah

  • Password: Sarah_pass123

Sarah can see:

  • Max's merged changes

  • Her own commits preserved

  • Complete story collection

📸 Screenshot 8: Sarah's view of repository

TASK COMPLETE! 🎉🎊🎈🎊🎉

🔍 Understanding What We Accomplished

The Complete Resolution Flow

INITIAL STATE (Diverged):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Max's Local:
A  B  C  M1  M2
Issues: 
- story-index.txt incomplete (3/4 stories)
- story1.txt has typo "Mooose"

Remote (Gitea):
A  B  C  S1  S2 (Sarah's commits)

Problem: git push REJECTED!

STEP 1: Fix Local Issues
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Actions:
- Fix typo: Mooose  Mouse
- Add story 4 to index
- Commit: M3

Max's Local Now:
A  B  C  M1  M2  M3

STEP 2: Pull Remote Changes
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Command: git pull origin master

Git performs:
1. Fetch S1, S2 from remote
2. Merge with M1, M2, M3
3. Create merge commit M4

Max's Local After Pull:
     M1  M2  M3  M4 (merge)
    /              /
A  B  C  S1  S2

STEP 3: Push Successfully
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Command: git push origin master

Remote After Push:
     M1  M2  M3  M4
    /              /
A  B  C  S1  S2

Result:
 Both Sarah and Max's work preserved
 Merge commit shows integration
 Complete story index (4 titles)
 Typo fixed
 Push successful!

What Each Commit Contains

Commit Timeline:

C: Base commit
└─ Original repository state

S1: Sarah's commit 1
└─ Updated story2.txt formatting

S2: Sarah's commit 2
└─ Added details to story3.txt

M1: Max's commit 1
└─ Updated story-index.txt (partial)

M2: Max's commit 2
└─ Added story4.txt

M3: Max's commit 3 (our fix)
└─ Fixed typo: Mooose  Mouse
└─ Completed index with all 4 stories

M4: Merge commit
└─ Parent 1: M3 (Max's branch)
└─ Parent 2: S2 (Sarah's branch)
└─ Combined both branches

The Merge Commit Structure

Merge Commit (M4):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
commit p6q7r8s9t0u1v2w3x4y5z6a7b8c9d0e1f2g3h4i5
Merge: n3o4p5q s2a1b2c
Author: Max <max@example.com>
Date:   Sat Dec 07 12:00:00 2025

    Merge branch 'master' of /opt/story-blog

Parents:
├─ n3o4p5q (Max's latest commit)
└─ s2a1b2c (Sarah's latest commit)

Tree:
├─ story-index.txt (all 4 titles) 
├─ story1.txt (typo fixed) 
├─ story2.txt (Sarah's formatting) 
├─ story3.txt (Sarah's details) 
└─ story4.txt (Max's addition) 

This commit brings both branches together!

💡 Key Takeaways

Push conflicts occur when remote has commits you don't have locally ✨ Git protects against overwriting others' work ✨ Solution: Pull first, then push ✨ Git pull = git fetch + git merge ✨ Merge commits have two parents (both branches) ✨ Conflicts possible during merge - resolve manually ✨ Always pull before pushing in collaborative projects ✨ Fix local issues before attempting push ✨ Verify on UI after successful push ✨ Both works preserved through proper merging ✨ Communication helps - coordinate with team

🎓 Interview Questions

Q1: Explain what causes a "non-fast-forward" push rejection and how to resolve it.

Answer: Non-fast-forward rejection occurs when remote history diverged from local:

What is fast-forward: Fast-forward means local is simply behind remote: bash Remote: A → B → C Local: A → B Can fast-forward: Just move local pointer to C No merge needed (linear)

Non-fast-forward rejection: Non-fast-forward means branches diverged: bash Remote: A → B → C → D Local: A → B → E ↑ Can't fast-forward: histories diverged Both have commits after B

Why Git rejects: bash git push origin master To remote.git ! [rejected] master -> master (non-fast-forward) Reason: Remote has D (you don't have) Local has E (remote doesn't have) Risk: Push would overwrite D Git protection: Prevents data loss How to resolve - Option 1: Pull and merge (most common): bash # 1. Pull remote changes git pull origin master # Git fetches D and merges # Creates merge commit M # 2. Now push git push origin master # Result: A → B → C → D ← M \ / E Option 2: Rebase (linear history): bash # 1. Fetch remote git fetch origin # 2. Rebase local onto remote git rebase origin/master # Replays E on top of D # 3. Force push git push origin master --force-with-lease # Result: A → B → C → D → E' Option 3: Force push (dangerous!): bash git push origin master --force # Overwrites remote D with E # D is lost! Use only if: you're sure remote commits are wrong

Our task used Option 1: Pull and merge because: preserves both works (Max and Sarah), safest approach, standard collaboration, audit trail maintained. Prevention: Pull before starting work, pull frequently during work, communicate with team, push small changes often. Real scenario: bash Monday 9am: Pull latest Friday 5pm: Try to push Rejection: 50 commits behind! Solution: git pull (big merge) Alternative: git fetch && git rebase origin/master Decision tree: bash Push rejected? ├─ Want to preserve all history? └─ git pull (merge) ├─ Want linear history? └─ git fetch && git rebase └─ Sure remote is wrong? └─ git push --force (dangerous!)

Q2: What's the difference between git pull and git fetch? When would you use each?

Answer: Pull and fetch both get remote changes but differ in local integration: git fetch (download only): bash git fetch origin What it does: Downloads commits from remote, updates remote-tracking branches (origin/master), does NOT modify local branches, working directory unchanged. After fetch: bash Local master: A → B → C (unchanged) origin/master: A → B → C → D → E (updated) Use when: Want to see remote changes first, check before integrating, need to inspect updates, working on something critical. git pull (download + integrate): bash git pull origin master What it does: Fetches from remote (like fetch), merges into current branch, updates working directory, equivalent to: fetch + merge. After pull: bash git fetch origin git merge origin/master Use when: Ready to integrate immediately, standard workflow (most common), trust remote changes, want automatic merge.

| Real workflows: Careful workflow (fetch first): bash # 1. Fetch to see what's new git fetch origin # 2. Compare changes git log HEAD..origin/master --oneline git diff HEAD origin/master # 3. Review looks good # 4. Merge manually git merge origin/master # Or rebase git rebase origin/master Quick workflow (pull directly): bash # Just pull git pull origin master # Trust the process! Our task: Used git pull because: standard collaboration, trust teammate's work, want automatic merge, typical workflow. Pull variants: bash # Pull with merge (default) git pull origin master # Pull with rebase git pull --rebase origin master # Equivalent to: git fetch origin git rebase origin/master When to use fetch: Before important work (see what changed), conflicting changes suspected (review first), learning what happened (git log), automated scripts (check first). When to use pull: Normal daily workflow, trust collaborators, want convenience, standard practice. Fetch-first safety: bash # Always safe workflow git fetch origin # Inspect if [ changes look good ]; then git merge origin/master else # Don't merge yet fi Best practice: Fetch regularly (every hour), pull when ready to integrate, review changes if uncertain, communicate with team!

Q3: Walk through what happens during a merge conflict resolution. How does Git track the conflict?

Answer: Merge conflicts occur when Git can't automatically combine changes: When conflicts happen: bash # Scenario: Both modified same file Sarah changed: line 10 of story-index.txt Max changed: line 10 of story-index.txt Git merge: Can't auto-merge! Needs human decision Git's conflict detection: During merge, Git performs three-way merge: bash Base: Common ancestor commit Ours: Current branch (HEAD) Theirs: Incoming branch (merging in) Git tries: Combine changes If conflict: Mark in file, pause merge What Git does internally: bash # During git pull origin master 1. Fetch remote commits 2. Find merge base (common ancestor) 3. Compare three versions: - Base (last common commit) - HEAD (your changes) - origin/master (their changes) 4. If same lines changed differently: → CONFLICT! 5. Mark conflicts in files 6. Create special files: .git/MERGE_HEAD (commit being merged) .git/MERGE_MSG (default merge message) .git/MERGE_MODE (merge state) 7. Wait for user resolution Conflict markers in file: bash # story-index.txt after conflict <<<<<<< HEAD (Current Change) 1. The Lion and the Mouse 2. The Tortoise and the Hare 3. The Fox and the Grapes 4. The Ant and the Grasshopper ======= (Separator) 1. The Lion and the Mouse 2. The Tortoise and the Hare 3. The Fox and the Grapes 4. The Boy Who Cried Wolf >>>>>>> origin/master (Incoming Change) Conflict resolution process: bash # Step 1: Identify conflicts git status # Shows: Unmerged paths: both modified: story-index.txt # Step 2: Open conflicted file nano story-index.txt # Step 3: Choose resolution # Option A: Keep HEAD version (Max's) # Option B: Keep incoming (Sarah's) # Option C: Combine both # Option D: Write new version # Step 4: Remove markers # Delete <<<<<<<, =======, >>>>>>> # Keep only final content # Step 5: Stage resolved file git add story-index.txt # Step 6: Complete merge git commit # Opens editor with default message # Or: git commit -m "Merge and resolve index conflict" Resolution strategies: Strategy 1: Keep ours: bash git checkout --ours story-index.txt git add story-index.txt Strategy 2: Keep theirs: bash git checkout --theirs story-index.txt git add story-index.txt Strategy 3: Manual merge: bash # Edit file to combine: 1. The Lion and the Mouse 2. The Tortoise and the Hare 3. The Fox and the Grapes 4. The Ant and the Grasshopper 5. The Boy Who Cried Wolf # Both versions included! Merge tools: bash # Use visual merge tool git mergetool # Opens configured tool (vimdiff, meld, etc.) # Helps resolve visually Checking resolution: bash # After editing, verify git diff --check # Check for leftover markers git diff --cached # See what's staged git status # Should show "all conflicts fixed" Aborting merge: bash # If resolution too complex git merge --abort # Returns to pre-merge state # Can try different approach Our task: Clean merge (no conflicts) because: Max and Sarah worked on different files, or different parts of files, Git auto-merged successfully. Complex conflict example: bash # Multiple files conflicted git status Unmerged paths: both modified: story-index.txt both modified: story1.txt both modified: story2.txt Resolve each: git add story-index.txt git add story1.txt git add story2.txt Then commit: git commit Prevention: Work on different files, pull frequently, communicate what you're editing, keep changes small, coordinate major edits!

Q4: Explain the difference between merge commit and fast-forward merge. When does each occur?

Answer: Git has two merge strategies depending on branch history: Fast-forward merge (no merge commit): Occurs when target branch hasn't diverged: bash Before merge: master: A → B feature: A → B → C → D ↑ (feature ahead) After: git merge feature master: A → B → C → D (fast-forwarded) ↑ (just moved pointer) No merge commit created, linear history maintained, just pointer movement, looks like feature never branched. Merge commit (creates commit): Occurs when branches diverged: bash Before merge: master: A → B → M1 → M2 feature: A → B → F1 → F2 ↑ (diverged at B) After: git merge feature master: A → B → M1 → M2 ← M (merge commit) \ / F1 → F2 Merge commit M created, has two parents (M2 and F2), shows branch integration, preserves full history. When fast-forward happens: bash Conditions: 1. No commits on target since branch 2. Feature is simply ahead 3. Linear history possible Example: # Feature branches from master git checkout -b feature # Commits on feature only git commit -m "F1" git commit -m "F2" # Master unchanged # Merge will fast-forward git checkout master git merge feature # Result: A → B → F1 → F2 (linear) When merge commit happens: bash Conditions: 1. Both branches have new commits 2. Histories diverged 3. Integration needed Example: # Both branches active Monday: git checkout -b feature Tuesday: commits on feature Wednesday: commits on master # Both have changes # Merge creates commit git checkout master git merge feature # Result: Merge commit Forcing behavior: Prevent fast-forward (always create merge commit): bash git merge feature --no-ff # Even if could fast-forward # Creates merge commit # Use when: Want to preserve branch history Only fast-forward (fail if can't): bash git merge feature --ff-only # Only if linear # Fails if diverged # Use when: Want guarantee of linear history Default behavior: bash git merge feature # Tries fast-forward first # If can't, creates merge commit # Configurable: git config merge.ff false # Never fast-forward git config merge.ff only # Only fast-forward Our task result: Merge commit created because: Max and Sarah both committed, branches diverged, integration needed, standard collaboration. Visual comparison: Fast-forward: bash Before: * C (feature) * B * A (master) After: * C (master, feature) * B * A Straight line! Merge commit: bash Before: * M2 (master) | * F2 (feature) * | F1 |/ * B * A After: * M (merge) master |\ | * F2 * | F1 |/ * B * A Diamond shape! Professional practices: Open source projects: Often require --no-ff (preserve context), show feature boundaries, clear history. Enterprise: May prefer linear (--ff-only), cleaner history, rebase before merge. Our task: Standard merge commit, shows collaboration, both works visible, audit trail!

Q5: How do you handle a situation where you accidentally committed to the wrong branch and need to move changes to the correct branch?

Answer: Common mistake - committed to master instead of feature branch: Scenario: bash # Oops! On master git status On branch master # Made changes, committed git commit -m "Feature work" # Should have been on feature-branch! Solution 1: Cherry-pick to correct branch (if not pushed): bash # Current: master has wrong commit # 1. Note commit hash git log -1 --oneline # abc123 Feature work # 2. Switch to correct branch git checkout feature-branch # 3. Cherry-pick the commit git cherry-pick abc123 # 4. Go back to master git checkout master # 5. Remove commit from master git reset --hard HEAD~1 # Result: # - feature-branch has commit # - master clean Solution 2: Create branch from commit (easiest): bash # On master with wrong commit git branch feature-branch # Creates branch at current commit # Reset master git reset --hard HEAD~1 # Or if master needs to go back further git reset --hard origin/master # Switch to new branch git checkout feature-branch # Result: commit on correct branch! Solution 3: Already pushed to wrong branch: bash # Pushed to master (problem!) # Can't easily remove # 1. Create feature branch from commit git checkout -b feature-branch master # 2. Cherry-pick to master if needed # (or leave as is) # 3. Revert on master if must remove git checkout master git revert <commit-hash> git push origin master # Now: master reverted, feature-branch has work Real example: bash # Morning: Meant to work on feature-auth git checkout master # Oops! Should be feature-auth # Hours of work... git add . git commit -m "Implement authentication" # Realize mistake! # Fix: git branch feature-auth # Create branch here git reset --hard origin/master # Reset master git checkout feature-auth # Switch to branch # All work preserved on correct branch! Prevention: bash # Always check current branch git branch # Shows current # Or in prompt PS1='[\u@\h \W$(git branch 2>/dev/null | grep "^*" | cut -d " " -f2)]\$ ' # Shows: [user@host dir (master)]$ # Use git aliases alias gcb='git rev-parse --abbrev-ref HEAD' # Check branch Multiple commits on wrong branch: bash # Made 5 commits on master # Should be on feature # 1. Note range git log master~5..master --oneline # 2. Create branch at current point git branch feature master # 3. Reset master git checkout master git reset --hard master~5 # 4. Switch to feature git checkout feature # All 5 commits now on feature! If changes not committed yet: bash # Modified files, not committed # On wrong branch # 1. Stash changes git stash save "WIP on wrong branch" # 2. Switch to correct branch git checkout correct-branch # 3. Apply stash git stash pop # Changes now on correct branch! Our task context: Worked on correct branch (master was where work should be), but illustrates importance of: checking current branch, pull before push, handle conflicts properly!

Q6: Describe strategies for preventing and handling push conflicts in a team environment.

Answer: Teams need strategies to minimize and handle push conflicts effectively: Prevention strategies: 1. Communication: bash Team practices: - Announce: "Working on story-index.txt" - Coordinate: "Will push to master at 2pm" - Update: "Pushed changes to master" - Tools: Slack, Teams, daily standups Reduces: Simultaneous edits to same files 2. Pull frequently: bash # Good practice git pull origin master # Every 1-2 hours # Or before starting new work git pull origin master git checkout -b new-feature # Reduces: Large divergence, massive conflicts 3. Small, frequent pushes: bash # Good: Push after each logical unit git commit -m "Add login form" git push origin feature-login # Bad: Push after week of work git commit -m "Entire feature" # (Now way behind master) 4. Feature branches: bash # Each developer on own branch git checkout -b feature-auth # Alice git checkout -b feature-payment # Bob # Work independently # Merge to master when ready # Reduces: Direct conflicts on master 5. Lock files (for critical edits): bash # Some systems support file locking git lfs lock config/database.yml # Edit file git lfs unlock config/database.yml Handling strategies: Strategy 1: Pull-first workflow: bash # Before every push git pull origin master # Resolve any conflicts # Then push git push origin master Strategy 2: Fetch and review: bash # Check remote first git fetch origin git log HEAD..origin/master --oneline # If changes exist git pull origin master # Else push directly git push origin master Strategy 3: Rebase workflow: bash # Update with rebase git fetch origin git rebase origin/master # Resolve conflicts # Force push git push origin feature-branch --force-with-lease Strategy 4: Protected branches: bash # GitHub/GitLab settings: - Require pull requests - Require reviews - Require CI to pass - No direct pushes to master Result: All changes via PRs, reduces conflicts Team workflows: GitHub Flow: bash 1. Branch from master 2. Work on feature 3. Push feature branch (no conflicts!) 4. Create PR 5. Review and merge 6. Delete feature branch Conflicts: Only during PR merge, easier to handle GitFlow: bash Branches: - master (production) - develop (integration) - feature/* (development) Workflow: - Features merge to develop - Develop merges to master Conflicts: Mostly in develop, not master Conflict resolution protocol: bash Team agreement: 1. If conflict in your domain: → You resolve 2. If conflict unclear: → Discuss with team 3. If conflict complex: → Pair program resolution 4. After resolution: → Test thoroughly 5. Document: → What conflicted, how resolved Tools and automation: Pre-push hooks: bash # .git/hooks/pre-push #!/bin/bash # Check if behind remote git fetch origin if ! git merge-base --is-ancestor origin/master HEAD; then echo "Behind origin/master! Pull first." exit 1 fi CI/CD checks: yaml # .github/workflows/check-conflicts.yml - name: Check for conflicts run: | git fetch origin git merge-base origin/master HEAD Merge queue (GitHub): Automatically queues and tests merges, prevents conflicts, ensures green builds. Metrics to track: bash Team health metrics: - Push rejection rate - Average time to resolve conflicts - Conflicts per week - Time between pulls Best teams: - Pull every 1-2 hours - < 5% rejection rate - Resolve in < 15 minutes Our task lessons: Sarah and Max needed: better communication, more frequent pulls, coordination on shared files, clear file ownership.

Best practices summary: ✅ Pull before starting work, ✅ Pull frequently during work, ✅ Push small changes often, ✅ Use feature branches, ✅ Communicate with team, ✅ Resolve conflicts quickly, ✅ Test after resolution, ✅ Document complex resolutions!

🌟 Advanced Conflict Resolution

Using Merge Tools

Configure merge tool:

# Set up merge tool
git config --global merge.tool vimdiff
# Or: meld, kdiff3, p4merge

# When conflicts occur
git mergetool

# Opens visual diff tool
# Shows: BASE, LOCAL, REMOTE, MERGED
# Choose changes visually

Ours vs Theirs Strategy

Resolve entire file at once:

# Keep our version (local)
git checkout --ours conflicted-file.txt
git add conflicted-file.txt

# Keep their version (remote)
git checkout --theirs conflicted-file.txt
git add conflicted-file.txt

# Useful for: binary files, large conflicts

Rerere (Reuse Recorded Resolution)

Remember conflict resolutions:

# Enable rerere
git config --global rerere.enabled true

# Benefits:
# - Remembers how you resolved before
# - Auto-applies same resolution
# - Useful for rebases with same conflicts

Abort and Retry

If resolution goes wrong:

# Abort merge
git merge --abort

# Returns to pre-merge state
# Try different approach:
# - Rebase instead
# - Merge in chunks
# - Coordinate with team

🔧 Troubleshooting Push Issues

Issue 1: "Repository Not Found"

Error:

git push origin master
fatal: repository '/opt/story-blog.git' not found

Solutions:

# Check remote URL
git remote -v

# Fix remote URL
git remote set-url origin /correct/path.git

# Or re-add remote
git remote remove origin
git remote add origin /correct/path.git

Issue 2: "Permission Denied"

Error:

git push origin master
Permission denied (publickey)

Solutions

# Check SSH keys
ls -la ~/.ssh/

# Generate new key if needed
ssh-keygen -t ed25519 -C "email@example.com"

# Add to ssh-agent
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519

# Add public key to Git server

Issue 3: "Large File Warning"

Error:

git push origin master
warning: Large files detected

Solutions:

# Remove large file from history
git filter-branch --tree-filter 'rm -f large-file.bin'

# Or use BFG Repo Cleaner
bfg --strip-blobs-bigger-than 100M

# Or use Git LFS
git lfs track "*.bin"

Issue 4: "Protected Branch"

Error:

git push origin master
remote: error: GH006: Protected branch update failed

Solutions:

# Can't push directly to protected branch
# Must use pull request:
git push origin feature-branch
# Then create PR via UI

# Or: ask admin to temporarily unprotect

🎯 Best Practices Summary

Daily Workflow

# Morning routine
git pull origin master

# During work (every 1-2 hours)
git add .
git commit -m "Checkpoint"
git pull origin master  # Stay synced
git push origin master

# End of day
git pull origin master
git push origin master

Pre-Push Checklist

# Before every push
☐ git status (clean working directory)
☐ git pull origin master (get latest)
☐ Resolve any conflicts
☐ Run tests (npm test, make test)
☐ git push origin master
☐ Verify on UI/remote

Conflict Resolution Checklist :

# When conflicts occur
☐ Don't panic!
☐ git status (identify conflicts)
☐ Open conflicted files
☐ Understand both changes
☐ Choose resolution strategy
☐ Remove conflict markers
☐ Test changes work
☐ git add <resolved-files>
☐ git commit (complete merge)
☐ git push origin master

🎉 Final Thoughts

You've mastered Git push conflict resolution! This is essential for team collaboration:

What you accomplished:

  • ✅ Identified push rejection cause

  • ✅ Fixed local file issues (typo, incomplete index)

  • ✅ Pulled remote changes successfully

  • ✅ Merged Sarah's and Max's work

  • ✅ Resolved any conflicts

  • ✅ Pushed merged changes

  • ✅ Verified on Gitea UI

  • ✅ Documented with screenshots

Real-world applications:

  • Team collaboration: Daily occurrence in development teams

  • Conflict resolution: Essential skill for any developer

  • Code integration: Combining multiple developers' work

  • Version control: Maintaining consistent repository state

  • Communication: Coordinating with teammates

This is professional teamwork! Handling conflicts gracefully keeps projects moving! 💪

Key principles to remember:

  1. Pull before push - always sync first

  2. Resolve conflicts carefully - understand both changes

  3. Test after merge - ensure everything works

  4. Communicate with team - coordinate changes

  5. Push frequently - small changes easier to merge

  6. Use feature branches - reduce direct conflicts

  7. Verify on UI - confirm successful integration

🚀 What's Next?

Day 33 complete! 🎉 You've mastered Git collaboration and conflict resolution!

Skills Mastered Today:

  • ✅ Git push conflict resolution

  • ✅ Pull and merge workflows

  • ✅ File error correction

  • ✅ Team collaboration

  • ✅ Gitea UI verification

  • ✅ Merge conflict handling

33 days strong! 🎊 One-third through the challenge! Keep the momentum! 💪


Day: 33/100
Challenge: KodeKloud Cloud DevOps
Date: December 08, 2025
Topic: Git Push Conflicts - Resolving Remote Conflicts

How often do you encounter push conflicts? What's your conflict resolution strategy? Share your collaboration stories! 🔀

More from this blog

🚀 DevOps Challenge- KodeKloud Solutions

73 posts