Skip to main content

I Have Multiple Changes But Only Want to Commit the Port Updateβ€”My Git Partial Staging Journey

Β· 13 min read
Mahmut Salman
Software Developer

I changed my dev server port from 5173 to 5174 across three files, but I also had other unrelated changes in those same files! 😰 I only wanted to commit the port changes. My mentor walked me through Git's partial staging features: git add -p, git stash, interactive staging, and patch mode. After some trial and error (and learning what NOT to do), I successfully committed only the port changes while keeping my other work-in-progress safe. This is professional Git workflow! 🎯

The Problem: Mixed Changes​

Me (Backend Dev): I just fixed a port conflict by changing from 5173 to 5174 in three files:

  • vite.config.js (line 15)
  • package.json (line 12)
  • src/main/main.js (line 230)

But here's the problem: I also have other changes in main.js (new IPC handler), database.js, and App.jsx that aren't ready yet!

I want to commit ONLY the port changes. How do I do that?

The Git Status Reality Check​

Frontend Mentor: Let me first show you what Git sees:

git status

Output:

On branch main
Changes not staged for commit:
modified: package.json
modified: src/main/database.js
modified: src/main/main.js
modified: src/preload/index.js
modified: src/renderer/App.jsx
modified: vite.config.js

The challenge:

  • βœ… vite.config.js - Only port change (safe to commit entirely)
  • βœ… package.json - Only port change (safe to commit entirely)
  • ⚠️ src/main/main.js - Port change PLUS new IPC handler (partial commit needed!)
  • ❌ database.js, preload/index.js, App.jsx - Only work-in-progress (skip entirely)

Understanding Git Staging Options​

Me: Can't I just do git add vite.config.js package.json main.js?

Frontend Mentor: That would stage ALL changes in main.js, including your WIP code! We need more precision.

Git Staging Levels​

Git gives you three levels of control:

Level 1: Stage Entire Files (Too Coarse)​

git add vite.config.js package.json src/main/main.js

Result: ❌ Stages the port change AND the IPC handler Problem: Commits unfinished work!

Level 2: Interactive Staging (Just Right!)​

git add -p src/main/main.js

Result: βœ… Git asks you hunk-by-hunk which changes to stage Perfect! Stage port change, skip IPC handler

Level 3: Manual Patch Editing (Advanced)​

git add -e src/main/main.js

Result: βœ… Opens editor to manually select lines Most precise, but complex!

The Journey: Trial and Error​

Me: Show me the journeyβ€”including the mistakes!

Frontend Mentor: Absolutely! Here's the real process, mistakes and all:

Attempt 1: Simple git add (Failed)​

git add vite.config.js package.json src/main/main.js
git diff --cached

What happened:

diff --git a/src/main/main.js b/src/main/main.js
@@ -227,7 +227,7 @@
});

const rendererUrl = isDev
- ? 'http://localhost:5173'
+ ? 'http://localhost:5174' ← βœ… Want this
: `file://${path.join(__dirname, '..', '..', 'dist', 'renderer', 'index.html')}`;

+// New IPC handler for database operations
+ipcMain.handle('database-query', async (event, query) => { ← ❌ Don't want this!
+ return await db.query(query);
+});

Problem: Staged both port change and IPC handler!

Fix: Reset and try again

git reset HEAD src/main/main.js

Attempt 2: Interactive Staging (Learning Curve)​

git add -p src/main/main.js

Git asks:

Stage this hunk [y,n,q,a,d,s,e,?]?

Me: Wait, what do these letters mean? 😡

Frontend Mentor: Here's the cheat sheet:

KeyActionWhen to Use
yYes, stage this hunkYou want this change
nNo, skip this hunkYou don't want this change
sSplit into smaller hunksHunk has both wanted & unwanted changes
eEdit hunk manuallyNeed precise line control
qQuit (stop staging)Made a mistake, start over
?Show helpLearn what each option does

Attempt 3: Interactive Staging (Success!)​

git add -p src/main/main.js

Git shows first hunk (port change):

@@ -227,7 +227,7 @@
});

const rendererUrl = isDev
- ? 'http://localhost:5173'
+ ? 'http://localhost:5174'
: `file://${path.join(__dirname, '..', '..', 'dist', 'renderer', 'index.html')}`;

Stage this hunk [y,n,q,a,d,s,e,?]?

Me types: y βœ… (Yes, stage the port change)

Git shows second hunk (IPC handler):

@@ -850,6 +850,11 @@
});
});

+// New IPC handler
+ipcMain.handle('database-query', async (event, query) => {
+ return await db.query(query);
+});
+
app.on('window-all-closed', () => {
Stage this hunk [y,n,q,a,d,s,e,?]?

Me types: n βœ… (No, skip the IPC handler)

Result:

[main c977432] chore: change development server port from 5173 to 5174
3 files changed, 3 insertions(+), 3 deletions(-)

Perfect! Only port changes committed! πŸŽ‰

The Complete Workflow​

Me: Walk me through the complete workflow step-by-step.

Frontend Mentor: Here's the production-ready process:

Step 1: Check Current Status​

git status

Output:

Changes not staged for commit:
modified: package.json ← Port change only
modified: src/main/database.js ← WIP only
modified: src/main/main.js ← Port change + WIP
modified: src/renderer/App.jsx ← WIP only
modified: vite.config.js ← Port change only

Step 2: Stage Files with Only Port Changes​

git add vite.config.js package.json

Why: These files have only port changes, safe to stage entirely.

Step 3: Interactively Stage Partial Changes​

git add -p src/main/main.js

Interactive session:

Hunk 1: Port change (5173 β†’ 5174)
Stage this hunk? y βœ…

Hunk 2: New IPC handler
Stage this hunk? n ❌

Hunk 3: Import statement
Stage this hunk? n ❌

Step 4: Verify Staged Changes​

git diff --cached

Should show ONLY:

diff --git a/package.json b/package.json
@@ -9,7 +9,7 @@
"scripts": {
"dev": "cross-env NODE_ENV=development concurrently \"npm:dev:vite\" \"npm:dev:electron\"",
"dev:vite": "vite",
- "dev:electron": "wait-on tcp:5173 && electron . --enable-logging",
+ "dev:electron": "wait-on tcp:5174 && electron . --enable-logging",
"build": "rimraf dist && cross-env NODE_ENV=production vite build && electron-builder build --publish=never",

diff --git a/src/main/main.js b/src/main/main.js
@@ -227,7 +227,7 @@
});

const rendererUrl = isDev
- ? 'http://localhost:5173'
+ ? 'http://localhost:5174'
: `file://${path.join(__dirname, '..', '..', 'dist', 'renderer', 'index.html')}`;

diff --git a/vite.config.js b/vite.config.js
@@ -12,7 +12,7 @@
},
publicDir: path.resolve(__dirname, 'public'),
server: {
- port: 5173,
+ port: 5174,
strictPort: true
},

Perfect! Only port changes, no WIP code! βœ…

Step 5: Create the Commit​

git commit -m "chore: change development server port from 5173 to 5174

- Update Vite config to use port 5174
- Update package.json dev:electron script to wait for 5174
- Update main.js renderer URL to load from 5174
- Resolves port conflict with another service"

Step 6: Verify Commit Contents​

git log -1 --stat

Output:

commit c977432f8d93a54faf3af7fbbc528a70bbe30ab6
Author: Mahmut Salman <csmahmutsalman@gmail.com>
Date: Wed Oct 29 14:39:47 2025 +0300

chore: change development server port from 5173 to 5174

- Update Vite config to use port 5174
- Update package.json dev:electron script to wait for 5174
- Update main.js renderer URL to load from 5174
- Resolves port conflict with another service

package.json | 2 +-
src/main/main.js | 2 +-
vite.config.js | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)

Perfect! Clean commit with only port changes! 🎯

Step 7: Check Remaining Changes​

git status

Output:

Changes not staged for commit:
modified: src/main/database.js
modified: src/main/main.js ← Still has IPC handler change
modified: src/renderer/App.jsx

Excellent! WIP changes remain unstaged for future commits! βœ…

Advanced Technique: git stash for Temporary Isolation​

Me: What if I want to temporarily hide my WIP changes to see only port changes?

Frontend Mentor: Great question! Use git stash:

The Stash Workflow​

# Step 1: Stash WIP changes in specific files
git stash push -m "WIP: database and UI changes" \
src/main/database.js \
src/renderer/App.jsx

# Step 2: Now only port-related changes remain
git status

Output:

Changes not staged for commit:
modified: package.json
modified: src/main/main.js ← Only port change now!
modified: vite.config.js
# Step 3: Stage and commit port changes
git add -A
git commit -m "chore: change dev server port from 5173 to 5174"

# Step 4: Bring back WIP changes
git stash pop

Result:

  • βœ… Port changes committed cleanly
  • βœ… WIP changes restored
  • βœ… No mixing of concerns!

Common Mistakes and How to Fix Them​

Me: What mistakes should I avoid?

Frontend Mentor: Here are the classics!

Mistake 1: Staging Everything​

❌ WRONG:
git add .
git commit -m "chore: update port"

Problem: Commits ALL changes, including WIP code!

βœ… RIGHT:
git add vite.config.js package.json
git add -p src/main/main.js
git commit -m "chore: update port"

Mistake 2: Forgetting to Verify Staged Changes​

❌ WRONG:
git add -p src/main/main.js
git commit -m "chore: update port" ← Didn't check what was staged!

Problem: Might commit unwanted hunks!

βœ… RIGHT:
git add -p src/main/main.js
git diff --cached ← Verify before committing!
git commit -m "chore: update port"

Mistake 3: Committing localResources/ Changes​

❌ WRONG:
git add localResources/stop-app.sh ← Personal dev script!
git commit -m "chore: update port"

Problem: Commits local development files that shouldn't be in version control!

βœ… RIGHT:
# Only commit project files, skip localResources
git add vite.config.js package.json src/main/main.js
git commit -m "chore: update port"

Mistake 4: Using git add -u Without Checking​

❌ WRONG:
git add -u ← Stages ALL modified tracked files!
git commit -m "chore: update port"

Problem: Stages everything, including WIP!

βœ… RIGHT:
git add vite.config.js package.json
git add -p src/main/main.js
git commit -m "chore: update port"

The git add -p Interactive Mode Cheat Sheet​

Me: Give me a quick reference for interactive staging!

Frontend Mentor: Here's your command reference:

Interactive Staging Commands​

CommandFull NameWhat It DoesWhen to Use
yYesStage this hunkYou want this change
nNoSkip this hunkYou don't want this change
sSplitSplit into smaller hunksHunk mixes wanted & unwanted
eEditManually edit hunkNeed line-by-line control
qQuitStop and exitMade a mistake, start over
aAllStage this and all remainingAll remaining hunks are wanted
dDoneSkip this and all remainingAll remaining hunks unwanted
?HelpShow command helpLearn what options do

Real-World Example Session​

git add -p src/main/main.js

Session transcript:

diff --git a/src/main/main.js b/src/main/main.js
@@ -227,7 +227,7 @@
const rendererUrl = isDev
- ? 'http://localhost:5173'
+ ? 'http://localhost:5174'
: `file://${...}`;
Stage this hunk [y,n,q,a,d,s,e,?]? y ← YES! Stage port change
@@ -850,6 +850,11 @@
});
});

+// New IPC handler
+ipcMain.handle('database-query', async (event, query) => {
+ return await db.query(query);
+});
+
app.on('window-all-closed', () => {
Stage this hunk [y,n,q,a,d,s,e,?]? n ← NO! Skip WIP handler

Result: Only port change staged! βœ…

Visual Guide: What Gets Committed​

Me: Show me visually what happened!

Frontend Mentor: Here's the before and after:

Before Partial Staging​

Working Directory (All Changes):
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ vite.config.js β”‚
β”‚ - port: 5173 β†’ 5174 βœ… β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ package.json β”‚
β”‚ - port 5173 β†’ 5174 βœ… β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ src/main/main.js β”‚
β”‚ - port 5173 β†’ 5174 βœ… β”‚
β”‚ + new IPC handler ❌ (WIP) β”‚
β”‚ + import statement ❌ (WIP) β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ src/main/database.js β”‚
β”‚ + new query method ❌ (WIP) β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ src/renderer/App.jsx β”‚
β”‚ + new UI component ❌ (WIP) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Goal: Commit only βœ… changes, keep ❌ changes unstaged

After Interactive Staging​

Staging Area (What Will Be Committed):
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ βœ… vite.config.js β”‚
β”‚ - port: 5173 β†’ 5174 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ βœ… package.json β”‚
β”‚ - port 5173 β†’ 5174 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ βœ… src/main/main.js (partial) β”‚
β”‚ - port 5173 β†’ 5174 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Working Directory (Remaining Changes):
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ ❌ src/main/main.js β”‚
β”‚ + new IPC handler β”‚
β”‚ + import statement β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ ❌ src/main/database.js β”‚
β”‚ + new query method β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ ❌ src/renderer/App.jsx β”‚
β”‚ + new UI component β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Perfect! ✨ Only port changes staged for commit

Pro Tips for Partial Commits​

Me: Any pro tips for this workflow?

Frontend Mentor: Absolutely! Here are advanced techniques:

Tip 1: Use Descriptive Commit Messages​

βœ… GOOD:
git commit -m "chore: change development server port from 5173 to 5174

- Update Vite config to use port 5174
- Update package.json dev:electron script to wait for 5174
- Update main.js renderer URL to load from 5174
- Resolves port conflict with another service"

❌ BAD:
git commit -m "update port"

Tip 2: Verify Before Committing​

# Always check what's staged
git diff --cached

# Verify unstaged changes remain
git diff

# Double-check commit will be clean
git status

Tip 3: Use Git Aliases for Speed​

# Add to ~/.gitconfig
[alias]
ap = add -p
dc = diff --cached
st = status -sb
unstage = reset HEAD --

Usage:

git ap src/main/main.js     # Instead of: git add -p src/main/main.js
git dc # Instead of: git diff --cached
git st # Instead of: git status -sb

Tip 4: Split Large Hunks​

git add -p src/main/main.js

If Git shows a huge hunk:

Stage this hunk [y,n,q,a,d,s,e,?]? s  ← Split it!

Git breaks it into smaller hunks for more precise control!

Tip 5: Use git log to Verify Commit​

# View last commit details
git log -1 -p

# View file changes in last commit
git log -1 --stat

# View last commit with diff
git show HEAD

When to Use Partial Staging​

Me: When should I use this technique vs. just making separate commits?

Frontend Mentor: Great question! Here's the decision guide:

Use Partial Staging When:​

βœ… Mixed concerns in same file

  • Port change + new feature in main.js
  • Bug fix + refactoring in same function
  • Config update + experimental code

βœ… Quick fixes during feature work

  • Typo fix while developing new feature
  • Documentation update during implementation
  • Performance tweak while building UI

βœ… Urgent hotfix with WIP

  • Security fix needed immediately
  • Production bug during feature development
  • Critical config change while experimenting

Don't Use Partial Staging When:​

❌ Changes are in different files

  • Just stage complete files instead
  • Simpler and clearer

❌ All changes are related

  • Commit everything together
  • Tells complete story

❌ Changes are too intertwined

  • Difficult to separate cleanly
  • Consider finishing or stashing WIP first

Key Takeaways​

Me: Let me summarize what I learned!

Frontend Mentor: Perfect! Here's your complete guide:

The Workflow​

Step 1: git status                    ← See all changes
Step 2: git add [simple-files] ← Stage files with only wanted changes
Step 3: git add -p [mixed-file] ← Interactively stage hunks
Step 4: git diff --cached ← Verify what's staged
Step 5: git commit -m "message" ← Commit staged changes
Step 6: git status ← Verify WIP remains unstaged

The Commands​

CommandPurposeExample
git add file.jsStage entire filegit add vite.config.js
git add -p file.jsInteractive staginggit add -p main.js
git diff --cachedView staged changesAlways run before commit!
git reset HEAD file.jsUnstage fileFix staging mistakes
git stash push -m "msg" filesTemporarily hide changesIsolate changes

The Interactive Keys​

KeyActionUse When
yStage hunkWant this change
nSkip hunkDon't want this change
sSplit hunkHunk too big
eEdit hunkNeed precise control
qQuitStart over

Remember:​

"Stage with precision, commit with confidence!"

  • git add -p for mixed files
  • git diff --cached before committing
  • Verify with git log -1 --stat
  • Keep WIP unstaged for future commits

Me: This is amazing! I went from "how do I commit only the port changes?" to successfully creating a clean, focused commit while keeping my WIP safe. The interactive staging with git add -p is a game-changer!

Frontend Mentor: Exactly! 🎯 You've just leveled up your Git skills! This is professional version control:

  1. βœ… Focused commits - One concern per commit
  2. βœ… Clean history - Easy to understand and review
  3. βœ… Safe WIP - Work-in-progress protected
  4. βœ… Easy rollback - Can revert port change without losing WIP

You went from git add . (the hammer) to git add -p (the scalpel). Now you can make surgical commits even when your working directory is messy! πŸ”ͺ✨

Go forth and make beautiful, atomic commits! πŸ’ͺ


Have you used Git partial staging before? Share your favorite techniques in the comments! πŸŽ¨πŸ’¬