Anders Tall

macOS, end to end: APFS containers, volumes, clones

4 min read

APFS replaced HFS+ as the macOS default in 2017, and it doesn’t think in partitions. It thinks in containers and volumes: one pool of space, many volumes, all sharing it. The videos were recorded on a MacBook Pro M3 (macOS 26.6.2) with a disposable 2 GB USB disk, never the internal one; this page explains why the commands work.

The model

physical disk        disk4
  └── physical store disk4s1
        └── container  disk5        (the pool)
              ├── volume disk5s1     data
              └── volume disk5s2     data2

The device numbers vary; check diskutil list external on your own Mac.

A container owns the space; volumes are lightweight namespaces inside it. That is why two volumes can both report 1.9 GiB free: they are not partitions with fixed borders, they are views into the same pool.

Create it

On a blank disk:

diskutil list external
sudo diskutil eraseDisk APFS data GPT /dev/disk4
diskutil list external

eraseDisk is the mkfs equivalent — it writes a GPT, an APFS container and the first volume. The volume mounts at /Volumes/data. Then the usual proof:

echo 'hello from apfs' > /Volumes/data/hello.txt
cat /Volumes/data/hello.txt
df -h /Volumes/data

Watch on YouTube →

Add a volume

diskutil apfs list disk5
sudo diskutil apfs addVolume disk5 APFS data2
df -h /Volumes/data /Volumes/data2

Both volumes now show the same capacity and free space. diskutil apfs list disk5 is the map: physical store → container → volumes, with UUIDs, roles and consumed space.

To remove one: sudo diskutil apfs deleteVolume disk5s2. The space returns to the container immediately.

Watch on YouTube →

Grow and shrink

APFS resizes the container, not each volume:

sudo diskutil apfs resizeContainer disk5 1g
sudo diskutil apfs resizeContainer disk5 0

This is the opposite of XFS and ZFS: APFS grows and shrinks, and it does it at the container level.

Watch on YouTube →

Clones (the APFS party trick)

APFS is copy-on-write, and cp -c exposes it directly:

yes 'hello apfs' | head -n 3000000 > big.txt
cp -c big.txt big-clone.txt

cp -c does not copy the 31 MiB; it creates a clone that shares the same blocks. It is instant, and the free space does not move. When one side is modified, APFS copies only the changed block:

echo 'changed' >> big.txt
tail -2 big.txt          # hello apfs / changed
tail -2 big-clone.txt    # hello apfs / hello apfs
shasum big.txt big-clone.txt

The clone is independent after the edit, but it never paid for the initial copy. That is the same mechanism snapshots use — and a genuinely useful tool for backups, build caches and “I want a copy, but not 40 GB of one”.

Watch on YouTube →

A note on APFS snapshots

APFS snapshots exist, but on macOS they are Time Machine local snapshots:

tmutil localsnapshot
tmutil listlocalsnapshots /
sudo mkdir /tmp/snap
sudo mount_apfs -s com.apple.TimeMachine.2026-10-29-120000.local /System/Volumes/Data /tmp/snap

Two practical limits:

That is why the video series uses clones for the copy-on-write episode: same mechanism, works on any APFS volume, and the result is visible in df.

Verify it

diskutil verifyVolume /Volumes/data
sudo diskutil unmount /Volumes/data
sudo diskutil unmount /Volumes/data2
sudo fsck_apfs -n /dev/disk5s1
sudo diskutil mount disk5s1
sudo diskutil mount disk5s2

Watch on YouTube →

APFS vs HFS+

What to remember

Part of Filesystems, end to end.

#macos #apfs #diskutil #clones #filesystem #storage #homelab #devops