Perforce P4 file deletion
The following is an AI generated summary of the video
Why Perforce Leaves Empty Folders Behind After You Delete Files
If you've ever deleted files from a Perforce (P4) workspace and wondered why the directories are still sitting there afterwards, you're not alone. This catches out a lot of Unreal Engine developers in particular.
The confusion usually comes from assuming that Perforce versions directories as well as files. It doesn't.
Once you understand that distinction, the behaviour makes perfect sense.
The Depot Is the Source of Truth
Perforce is a centralised version control system. The depot is the canonical copy of your project, and every workspace simply syncs files to and from it.
A developer might have multiple workspaces—for example:
- a Windows workstation
- a Mac laptop
These workspaces don't communicate with each other directly. They only communicate with the depot.
Perforce Versions Files, Not Directories
This is the key concept.
Imagine a project containing:
playground/
├── bar.txt
└── gav-test/
└── bip.txt
It's tempting to think Perforce is tracking three things:
bar.txtgav-testbip.txt
In reality, it only tracks two files.
The directory isn't an object in the depot. It's simply part of the file's path.
From Perforce's perspective, gav-test/bip.txt is just a filename that happens to contain slashes.
This is similar to object storage systems such as Amazon S3, where directories are largely an illusion created from path prefixes.
What Happens When You Delete Files?
Suppose both files are marked for deletion and submitted.
The depot now records that:
bar.txthas been deletedgav-test/bip.txthas been deleted
Notice what's missing.
There's no operation relating to the directory itself, because there never was a directory object to delete.
Why the Empty Folder Stays Behind
After syncing those deletions, you'll typically find:
- the files have disappeared
- the directory is still present
That surprises many people.
The reason is simple:
Perforce removes the files because it manages files.
Your operating system created the directory, so your operating system leaves it there once it's empty.
Perforce doesn't perform any automatic cleanup of empty folders because, as far as it's concerned, they don't exist.
Fresh Workspace vs Existing Workspace
This becomes clearer if you compare two scenarios.
Existing workspace
You already had the files checked out.
After syncing:
- deleted files disappear
- empty directories remain
Brand new workspace
You create a completely fresh workspace and sync the latest revision.
This time, the empty directory never appears at all, because there are no files requiring it to exist.
That's the important distinction:
- syncing removes files
- fresh checkouts only create directories needed for existing files
What About Other Developers?
Exactly the same rules apply.
If another developer syncs after you've submitted a deletion:
- the deleted files disappear
- any now-empty directories remain in their workspace
Nothing is broken.
They're simply left with an empty folder that Perforce has no reason to remove.
Should You Worry?
Not really.
The downside is mostly cosmetic. Empty folders can make people wonder whether something has gone wrong.
In practice you have a few options:
- delete empty folders manually
- run a small cleanup script that removes empty directories
- simply understand that they're harmless
The important thing is that everyone on the team understands why they're there.
Takeaway
The behaviour becomes much less mysterious once you remember one simple rule:
Perforce versions files, not directories.
Deleting every file inside a directory removes those files from the depot and from other developers' workspaces when they sync.
What it doesn't do is remove the empty directory from an existing local workspace.
A fresh checkout won't contain that directory because there's nothing to populate it, but an existing workspace will keep it until you delete it yourself.
Once you understand that distinction, Perforce's behaviour is entirely consistent—and much less confusing.