Skip to main content

Git's Asterisk Won't Go Away: Understanding 'deleted:' in Git Status

Β· 13 min read
Mahmut Salman
Software Developer

I just made a commit, so why does VS Code still show that asterisk (*) on my branch name? A debugging journey through Git's "deleted" file status and what to do about it.


The Mysterious Asterisk​

It's a typical coding session. I've just committed my changesβ€”a nice feature adding cursor position memory to my application. The commit went through successfully. But something's wrong.

The asterisk is still there.

Bottom left corner of VS Code:
πŸ”€ main *
↑
Why are you still here?!

In VS Code, that * indicator means there are uncommitted changes. But I just committed! What's going on?


The Investigation Begins​

I run git status to see what Git thinks is happening:

$ git status

On branch main
Your branch is ahead of 'origin/main' by 1 commit.

Changes not staged for commit:
deleted: resources/jdt-language-server/config_mac_arm/org.eclipse.core.runtime/.manager/.tmp3.instance

no changes added to commit

Wait... deleted:?

My immediate questions:

  • πŸ€” What does "deleted:" mean?
  • πŸ€” Why is Git tracking the deletion of a file?
  • πŸ€” I didn't delete anything manuallyβ€”what happened?
  • πŸ€” Should I add this to .gitignore?
  • πŸ€” Should I just commit it as a chore?
  • πŸ€” How do I make that asterisk go away?!

Understanding "deleted:" in Git Status​

What "deleted:" Actually Means​

When you see deleted: in git status, it means:

βœ… The file WAS tracked by git (it was committed before)
βœ… The file NO LONGER EXISTS on your filesystem
❓ Git is asking: "Should I record this deletion in the next commit?"

Visual representation:

Before:
Your disk: [file exists]
Git: [tracking file] βœ“

Now:
Your disk: [file gone!]
Git: [still tracking file] ❓ "What should I do?"

Why This Is Different from Untracked Files​

# Untracked file (never committed):
Untracked files:
new-file.txt # Git says: "I've never seen this before"

# Deleted file (was committed, now gone):
Changes not staged:
deleted: old-file.txt # Git says: "This used to be here, where did it go?"

The Full Story: What Actually Happened​

The Timeline​

1. Past Mistake (Weeks/Months Ago)

# Someone (probably me) accidentally committed a temp file:
git add resources/jdt-language-server/.../tmp3.instance
git commit -m "some commit"

❌ This was a mistake! Temporary cache files should never be committed.

2. Normal Application Usage (Today)

# I run my Java application
# Eclipse JDT Language Server creates temp cache files
# I stop the application
# Eclipse automatically cleans up temp files
# The tmp3.instance file gets deleted

βœ… This is normal! Applications clean up their temp files.

3. Git Notices the Change

$ git status

deleted: resources/jdt-language-server/.../tmp3.instance

Git is like: "Hey! You committed this file before, and now it's gone. Should I record that it's deleted?"

4. I Make Another Commit (Cursor Memory)

git add src/cursor-memory.java
git commit -m "feat: add cursor position memory"

The commit succeeds, but the deleted file is still not staged, so * remains!


The Confusion: What Should I Do?​

When you see a deleted file in git status, you have two options:

Option 1: Commit the Deletion​

Tell Git: "Yes, this file should be removed from version control"

git add -u  # Stage all updates including deletions
# or
git rm <file> # Explicitly remove and stage

Use this when:

  • βœ… You intentionally deleted a source file
  • βœ… The file is no longer needed in the project
  • βœ… You want to remove it from version control

Option 2: Restore the File​

Tell Git: "No, bring the file back!"

git restore <file>  # Restore from last commit

Use this when:

  • βœ… You accidentally deleted an important file
  • βœ… The file should exist but got removed by mistake

My Case: Neither Option Worked Immediately!​

This was a temporary cache file that should never have been tracked. So:

  • ❌ I don't want to restore it (it's a temp file)
  • ❌ But I also want to prevent this from happening again

Solution: Add to .gitignore + commit the deletion


The First Attempt: Errors Everywhere​

Let me try to fix this by staging the deletion:

Error #1: Can't Add an Ignored File​

$ git add resources/jdt-language-server/config_mac_arm/org.eclipse.core.runtime/.manager/.tmp3.instance

The following paths are ignored by one of your .gitignore files:
resources/jdt-language-server/config_mac_arm/org.eclipse.core.runtime/.manager/.tmp3.instance
hint: Use -f if you really want to add them.

What?! I'm trying to stage a deletion, but Git is saying it's ignored?

Why this happened:

# I had just added this to .gitignore:
resources/jdt-language-server/config_mac_arm/

# Git sees I'm trying to "add" something in an ignored directory
# Git refuses: "That's ignored! I won't add it!"

But I'm not adding it... I'm trying to stage its deletion! πŸ€¦β€β™‚οΈ

Error #2: Can't Remove a Non-Existent File​

$ git rm resources/jdt-language-server/.../tmp3.instance

fatal: pathspec 'resources/jdt-language-server/.../tmp3.instance' did not match any files

Why this failed:

  • git rm expects the file to exist on disk
  • It wants to delete the file AND stage the deletion
  • But the file is already gone! (Eclipse deleted it)
  • So git rm says: "I can't find anything to delete!"
git rm workflow:
1. Delete file from disk
2. Stage the deletion
↑
Can't do step 1 because file is already gone!

The Solution: .gitignore Magic​

Here's the trick that finally worked:

# 1. Make sure .gitignore has the pattern
$ echo "resources/jdt-language-server/config_mac_arm/" >> .gitignore

# 2. Stage .gitignore
$ git add .gitignore

# 3. Check status
$ git status

Changes to be committed:
modified: .gitignore
deleted: resources/jdt-language-server/.../tmp3.instance

Wait... I only staged .gitignore, but the deletion got staged too?!

Why This Works​

When you stage .gitignore, Git does something smart:

Git's Logic:
1. "Oh, .gitignore changed"
2. "Let me check what new patterns were added"
3. "Hmm, this pattern matches some tracked files"
4. "Those files are now ignored AND deleted"
5. "I'll automatically stage their deletions too!"

In other words:

  • Staging .gitignore tells Git about new ignore patterns
  • Git automatically stages deletions of files that match those new patterns
  • Both changes get staged together
$ git add .gitignore

Behind the scenes:
βœ… Stage .gitignore changes
βœ… Auto-stage deletions of newly-ignored files

The Final Commit​

Now both changes are staged:

$ git status

Changes to be committed:
modified: .gitignore
deleted: resources/jdt-language-server/.../tmp3.instance

$ git commit -m "chore: ignore Eclipse JDT temp files and remove tracked instance"

Finally! The asterisk is gone! ✨

πŸ”€ main
↑
No more asterisk!

Understanding the Full Picture​

What We Just Did​

  1. Added to .gitignore: Prevent future tracking of temp files
  2. Staged the deletion: Remove the existing tracked file from Git
  3. Committed together: Both changes in one logical commit

Why Both Steps Were Necessary​

Just .gitignore Alone βŒβ€‹

# Add to .gitignore
echo "temp/" >> .gitignore
git add .gitignore
git commit -m "ignore temp files"

# But the already-tracked temp file stays in git!
$ git ls-files | grep temp
temp/old-tracked-file.txt # Still tracked!

.gitignore only prevents Git from tracking new files. It doesn't remove already-tracked files.

Just Deletion Alone βŒβ€‹

# Stage the deletion
git add -u
git commit -m "remove temp file"

# But next time the app runs:
$ git status
Untracked files:
temp/new-file.txt # Git suggests tracking this!

Without .gitignore, Git will keep suggesting you add new temp files.

Both Together βœ…β€‹

# Add pattern + commit deletion
git add .gitignore
git commit -m "ignore temp files and remove tracked instances"

# Now and forever:
# - Old tracked files: removed from git
# - New temp files: automatically ignored
# - No more asterisk surprises!

The Right Approach for Different Scenarios​

Scenario 1: Temp/Cache Files (Our Case)​

Symptoms:

  • Application creates/deletes temp files automatically
  • You see deleted: for files you didn't manually remove
  • Files reappear after running the application

Solution:

# 1. Add pattern to .gitignore
echo "path/to/temp/files/" >> .gitignore

# 2. Stage .gitignore (auto-stages deletions)
git add .gitignore

# 3. Commit
git commit -m "chore: ignore temp files and remove tracked instances"

Scenario 2: Intentionally Removed Source Files​

Symptoms:

  • You manually deleted a source file
  • The file is legitimately no longer needed
  • This is a real project change

Solution:

# Option A: Stage all updates (deletions included)
git add -u
git commit -m "refactor: remove deprecated UserController"

# Option B: Explicitly stage the deletion
git rm path/to/file.java # If file still exists
# or
git add path/to/file.java # If already deleted
git commit -m "refactor: remove deprecated file"

Scenario 3: Accidentally Deleted Important File​

Symptoms:

  • You see deleted: for a file you need
  • File was deleted by mistake
  • You want it back!

Solution:

# Restore from last commit
git restore path/to/important/file.java

# Verify
$ git status
# (deleted file no longer appears)

Scenario 4: Build Artifacts​

Symptoms:

  • deleted: for compiled files (.class, .o, node_modules/)
  • These should never have been tracked

Solution:

# 1. Add to .gitignore
echo "build/" >> .gitignore
echo "*.class" >> .gitignore
echo "node_modules/" >> .gitignore

# 2. Remove all tracked files matching patterns
git rm -r --cached build/
git rm --cached '*.class'
git rm -r --cached node_modules/

# 3. Stage .gitignore
git add .gitignore

# 4. Commit
git commit -m "chore: ignore build artifacts and remove tracked files"

Note: The --cached flag tells Git to remove from tracking but keep on disk.


Common Mistakes and How to Avoid Them​

Mistake 1: Ignoring Files Already in Git​

# ❌ Wrong order:
git add accidentally-committed-file.log
git commit -m "add log"
echo "*.log" >> .gitignore # Too late! Already tracked!
git add .gitignore
git commit -m "ignore logs"

# The log file is still in git history!

Fix:

# Remove from tracking
git rm --cached accidentally-committed-file.log
git add .gitignore
git commit -m "chore: ignore logs and remove tracked file"

Mistake 2: Using git rm on Already-Deleted Files​

# File is already gone from disk
$ ls path/to/file.txt
ls: cannot access 'path/to/file.txt': No such file or directory

# This fails:
$ git rm path/to/file.txt
fatal: pathspec 'path/to/file.txt' did not match any files

# βœ… Use git add instead:
$ git add path/to/file.txt # Stages the deletion

Mistake 3: Committing Deletions Without .gitignore​

# ❌ Just commit deletion:
git add -u
git commit -m "remove temp files"

# Next time app runs:
$ git status
Untracked files:
temp/file1.tmp
temp/file2.tmp # They're back!

# βœ… Add to .gitignore first:
echo "temp/" >> .gitignore
git add .gitignore
git add -u
git commit -m "chore: ignore temp files and remove tracked instances"

Visual Guide: The Git Status Lifecycle​

Fresh File​

Action: Create new file
Status: Untracked
Command: git add <file>

Tracked File​

Action: git add + commit
Status: Tracked (clean)
Command: modify file

Modified File​

Action: Edit tracked file
Status: Modified (not staged)
Command: git add <file>

Staged Modification​

Action: git add
Status: Modified (staged)
Command: git commit

Deleted File (Our Case!)​

Action: Delete tracked file
Status: deleted: (not staged)
Command: git add <file> OR git add -u

Staged Deletion​

Action: Stage deletion
Status: deleted: (staged)
Command: git commit

Gone from Git​

Action: Commit deletion
Status: (file no longer tracked)
Add to .gitignore to prevent re-tracking

The Complete Checklist​

When you see deleted: in git status:

Step 1: Understand What Happened​

# Check the full path
git status

# Was it:
☐ A temp/cache file? β†’ Add to .gitignore
☐ An important source file? β†’ Restore it
☐ An intentional deletion? β†’ Commit it
☐ A build artifact? β†’ Add to .gitignore

Step 2: Take Appropriate Action​

For temp/cache/build files:

☐ Add pattern to .gitignore
☐ Stage .gitignore (auto-stages deletions)
☐ Commit with descriptive message
☐ Verify asterisk is gone

For intentional deletions:

☐ Stage deletion: git add -u or git add <file>
☐ Commit with explanation
☐ Verify asterisk is gone

For accidental deletions:

☐ Restore file: git restore <file>
☐ Verify file is back
☐ Verify asterisk is gone

Step 3: Prevent Future Issues​

☐ Review .gitignore patterns
☐ Add common patterns:
- **/temp/
- **/.cache/
- **/node_modules/
- **/*.log
- IDE-specific patterns
☐ Check git status before each commit
☐ Use git status -sb for concise view

Why .gitignore Doesn't Retroactively Untrack Files​

This is a common misconception:

What People Expect​

# Add to .gitignore
echo "temp/" >> .gitignore

# Expect: All temp files automatically untracked
$ git status
# (no temp files shown) # ❌ Doesn't happen!

What Actually Happens​

# Add to .gitignore
echo "temp/" >> .gitignore

# Reality: Already-tracked files stay tracked
$ git status
Changes not staged for commit:
deleted: temp/old-file.txt # Still shows up!

Why Git Works This Way​

Design Philosophy:

  • .gitignore affects future tracking decisions
  • It doesn't modify existing git history
  • Changing .gitignore shouldn't unexpectedly remove tracked files

Analogy:

.gitignore is like a "Do Not Enter" sign at a door

People already inside the room don't get kicked out
But new people trying to enter are turned away

To remove already-tracked files:

# Manual removal required:
git rm --cached <file> # or
git add .gitignore # (auto-stages deletions of newly-ignored files)

Pro Tips​

Tip 1: Check Before Committing​

# Always check status before commit
git status

# Or use short format:
git status -sb

## M src/main.java # Modified
## D temp/cache.tmp # Deleted
## ?? new-file.txt # Untracked

Tip 2: Use Aliases for Common Operations​

# Add to ~/.gitconfig
[alias]
st = status -sb
unstage = restore --staged
uncommit = reset --soft HEAD~1

# Now use:
git st # Short status

Tip 3: Global .gitignore​

# Create global ignore file
touch ~/.gitignore_global

# Add common patterns
echo ".DS_Store" >> ~/.gitignore_global
echo "*.swp" >> ~/.gitignore_global
echo "*.log" >> ~/.gitignore_global

# Configure git to use it
git config --global core.excludesfile ~/.gitignore_global

Tip 4: VS Code Git Indicators​

Understanding VS Code's git indicators:

M  - Modified (not staged)
A - Added (staged)
D - Deleted (not staged)
U - Untracked
C - Conflict
R - Renamed

Bottom left branch indicator:

main     - Clean (no changes)
main * - Uncommitted changes
main ↑1 - 1 commit ahead of remote
main ↓1 - 1 commit behind remote
main *↑1 - Changes + ahead

Key Takeaways​

What We Learned
  1. The * indicator means uncommitted changes - even if you just committed something else!

  2. deleted: in git status means:

    • File was previously tracked
    • File no longer exists on disk
    • Git needs to know if you want to commit this deletion
  3. Two main options for deleted files:

    • Commit the deletion (if intentional or temp file)
    • Restore the file (if accidental)
  4. The .gitignore + staging trick:

    • Staging .gitignore auto-stages deletions of newly-ignored files
    • This is the cleanest way to handle temp files
  5. .gitignore isn't retroactive:

    • Only affects future tracking decisions
    • Doesn't automatically untrack already-tracked files
    • Must manually remove tracked files that should be ignored
  6. Common scenarios:

    • Temp files: Add to .gitignore + commit deletion
    • Source files: Just commit the deletion
    • Accidents: Restore with git restore
    • Build artifacts: Add to .gitignore + git rm --cached
  7. Prevention is better than cure:

    • Set up .gitignore before first commit
    • Review git status before every commit
    • Use global .gitignore for system files

Conclusion​

That mysterious asterisk that wouldn't go away taught me something important: Git tracks the absence of files just as carefully as their presence.

When you commit a file to Git, you're not just saying "here's a file." You're saying "this file is part of my project." When that file disappears, Git notices and asks: "Is this intentional?"

The deleted file status isn't a bugβ€”it's Git being thorough. And once you understand what it means and how to handle it, those asterisks become informative rather than mysterious.

Next time you see:

deleted: some/path/to/file

You'll know exactly what happened and how to fix it! 🎯

Tags: #git #debugging #learning-journey #version-control #gitignore


This debugging session happened during actual development. Sometimes the best learning comes from those "wait, why is that still there?" moments.