Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

A Git commit points to a snapshot of tracked files; it does not store a patch. Git represents that snapshot with tree objects that point to file-content blobs, then compares commits to calculate the diffs it displays. Git does not alter an existing commit or blob in place, but objects can eventually be pruned after they are no longer protected by references or reflogs. So “Git never deletes anything” describes object immutability, not permanent retention.

What a Git commit actually stores

A commit object records a reference to the project’s root tree, its parent commit or commits, and metadata. The tree describes the tracked project state at that point in history. It is not a record of every file in a developer’s working directory: untracked files are not part of the committed snapshot.

A tree contains entries with a mode, object type, object ID, and name. An entry can point to a blob containing file contents, another tree representing a subdirectory, or a commit object used as a submodule gitlink. The object ID identifies an object’s contents under the repository’s Git object format.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Git’s current data-model manual puts it plainly: “Git does not store the diff for a commit: when you ask Git to show the commit with git-show[1], it calculates the diff from its parent on the fly.” The diff shown by a command such as git show is a comparison Git computes; it is not the commit’s stored payload.

How snapshots avoid duplicating every file

A snapshot describes the complete tracked state, but that does not mean Git makes a full independent copy of every file for every commit. When a file’s contents have not changed, a new tree can refer to the same blob object ID as an earlier tree. Changed files can have new blobs, while unchanged ones are reused.

This distinction explains how Git can behave as though each commit records a full snapshot without storing a separate duplicate of every unchanged file. The logical snapshot is complete; the underlying objects can be shared across snapshots.

What happens when you delete a file

Committing a file deletion creates a later tree that no longer contains that path. Earlier commits still point to trees that contain it, and those trees can point to the blob holding the previous contents. Deleting a file from the latest version therefore does not, by itself, remove it from earlier history.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

“Deleted from the current project” and “removed from all retained Git history” are different outcomes. If sensitive data was committed, a new deletion commit does not erase prior copies in the repository’s history. History rewriting may be needed, and collaborators with clones may also need to coordinate updates. Local Git behavior alone does not establish what a hosting service or its backups retain.

What amend, rebase, and reset do to commits

Git objects are immutable: the Git project’s data-model manual says, “Git objects never change after they’re created.” As a result, operations such as git commit --amend and rebase create replacement commits rather than editing the old commit objects in place.

Reset or another reference change can move a branch away from commits it previously named. Those commits may then be unreachable from that branch’s current tip, but they are not necessarily gone immediately. A tag, another reference, a remote-tracking branch, an index entry, or a reflog may still make the objects reachable or help locate them. Reflogs record changes to references; they are not a guarantee of indefinite retention.

When unreachable Git objects can be pruned

Unreachable means an object cannot be reached through the relevant references and object relationships; it does not mean it has already been erased. Git’s garbage-collection manual says that git gc “tries very hard not to delete objects that are referenced anywhere in your repository.” Garbage collection can later remove objects that are no longer protected and meet the applicable cleanup conditions.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The current online git-gc manual documents defaults, not recovery guarantees:

  • gc.pruneExpire behaves by default as if loose objects older than two weeks are eligible for pruning. It can be changed, set to now, or set to never.
  • Unreachable reflog entries default to a 30-day expiration through gc.reflogExpireUnreachable; ordinary reflog entries default to 90 days through gc.reflogExpire. The reflog manual documents reflog expiration and cleanup.

These periods are configurable defaults, not promises that a particular commit remains recoverable for exactly that long. References, object age, repository configuration, storage form, and maintenance activity all affect what remains available. The Git User Manual distinguishes loose objects from packed objects and describes pruning; unreachable packed objects may remain unless repacking handles them. Packing changes how objects are stored for efficiency, not the logical history represented by those objects.

Pruning immediately with --prune=now increases the risk of problems if another process is writing to the repository concurrently, as the git-gc manual warns. Do not treat garbage collection as a deterministic command that instantly deletes every unreachable object, or rely on an assumed recovery window.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

How to think about whether an old commit is still recoverable

There is no universal retention countdown. The relevant questions are whether a branch or tag still reaches the commit; whether another reference or reflog still points to it; whether the object is loose or packed; and what expiration and pruning settings apply in that repository. These are local Git questions. A hosted copy, backup, or another clone is separate and needs its own evidence about retention.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

If a commit has disappeared from a branch after amend, rebase, or reset, recovery may still be possible while a reflog or another reference preserves a path to it. But reflogs expire, settings differ, and maintenance may have run. Git’s object model supports neither a guarantee of permanent retention nor a guaranteed recovery period.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.