Skip to content
Foxipa

Suggest an edit

Tell us what should be corrected, clarified, or improved. Submission will be connected to Foxipa’s contribution service later.

No information is sent anywhere yet. Your suggestion is only prepared in your browser.

Learning

Git prune: Remove Unreachable Objects Safely

Understand Git's low-level object-pruning command, preview unreachable objects, control expiration, protect objects with additional heads, and distinguish pruning from integrity checking and general maintenance.

Levels: Advanced ~25 min read

Advanced

What `git prune` actually removes

Git can retain objects after they stop being reachable from refs. That retention is useful for recovery, but eventually unreachable objects can be removed. `git prune` is the low-level pruning command: it removes eligible unreachable objects from the object database and also invokes `git prune-packed` for loose objects that are already present in packs. In ordinary repository use, the official documentation recommends using `git gc` instead of invoking `git prune` directly.

bash
git prune -n -v --expire=now

Quick check

What is the primary purpose of `git prune`?

Why unreachable does not mean immediately deletable

Deleting a branch can make a commit unreachable from current refs while the object remains in the repository. Reflogs and other retention mechanisms are important in real repositories because they can preserve recovery paths. `git prune` should therefore not be treated as a command that simply deletes everything reported as interesting by `git fsck`. Before destructive pruning, inspect reachability and retention deliberately.

bash
git fsck --unreachable --no-reflogs
git reflog expire --expire=now --all
git fsck --unreachable --no-reflogs

Quick check

Why can an object remain present after its branch is deleted?

Preview first with `-n`

`-n` (or `--dry-run`) reports what would be pruned without removing it. `-v` makes the preview explicit by listing candidate objects. This is the safest form to demonstrate the effect before performing destructive cleanup.

bash
git prune -n -v --expire=now

Quick check

What does `git prune -n -v --expire=now` do?

Expiration controls eligibility

`--expire=<time>` controls how old an object must be before it is pruned. Using `--expire=now` is deliberately aggressive: an otherwise eligible unreachable object can be removed immediately. A normal expiration policy can leave a recovery window instead. Do not copy `--expire=now` into a real repository merely because it makes a demonstration deterministic.

bash
git prune -n -v --expire=now
git prune -n -v --expire=never

Quick check

What does `--expire=now` change?

Additional heads can protect objects

The command accepts optional `<head>` arguments. These extra object names are treated as heads when determining reachability, so objects reachable from them are protected from pruning during that invocation. This is a low-level mechanism for carefully defining what should remain reachable; it is not a substitute for making a durable ref when you actually want to preserve history.

bash
git prune -n -v --expire=now <head>

Quick check

What is the effect of supplying an additional `<head>` to `git prune`?

The remaining pruning controls

The official synopsis also exposes `--progress` and the argument separator `--`. `--progress` requests progress reporting. `--` stops option parsing so following arguments are treated as object names rather than options. These controls do not change which objects are reachable; they change reporting or argument interpretation.

bash
git prune -n -v --progress --expire=now
git prune -n -v --

Quick check

What is the purpose of `--` in the `git prune` command line?

Packed unreachable objects are a separate case

`git prune` removes unreachable unpacked objects. Unreachable objects that are already packed remain in their pack; the official documentation points to `git repack` when those packed unreachable objects must also be dealt with. `git prune` also removes unreachable entries from `.git/shallow`. This is another reason not to equate pruning with complete object repacking.

Quick check

What happens to an unreachable object that is already inside a pack?

`git prune` versus nearby commands

`git fsck` investigates object validity and connectivity; `git prune` removes eligible unreachable objects; `git gc` orchestrates repository housekeeping and is the normal high-level interface for maintenance. `git repack` reorganizes object packs, while `git pack-refs` reorganizes ref storage. These commands can appear together in maintenance workflows, but they have different ownership and destructive effects.

bash
git fsck --unreachable --no-reflogs
git prune -n -v --expire=now
git gc --no-prune
git repack -ad
git pack-refs --all

Quick check

Which command is the normal high-level maintenance interface rather than the low-level direct pruning operation?

Practice what you learned

Use the dedicated Git code-completion exercise for this lesson.

Was this page helpful?

Mark this learning resource complete to track your learning progress.