How to fix fatal: Objects must be of the same type to be replaced in Git

GitADVANCEDLOWUpdated Dec 6, 2025ยท 141 views

This Git error occurs when using git replace to substitute one object with another of a different type. Use the -f flag to force the replacement, or ensure both objects share the same type (commit, tree, blob, or tag).

Quick fix

Fixes fatal: Objects must be of the same type to be replaced

# Check the type of the original object
git cat-file -t <original-hash>

# Check the type of the replacement object
git cat-file -t <replacement-hash>
  1. Identify the types of both objects
  2. Use the -f flag to force replacement (if intentional)
  3. Find the correct object of the same type
  4. Replace commit with another commit
git โ€” error
# Check the type of the original object
git cat-file -t <original-hash>
# Check the type of the replacement object
git cat-file -t <replacement-hash>
fatal: Objects must be of the same type to be replaced

What this error means

The error "fatal: Objects must be of the same type to be replaced" occurs when you attempt to use `git replace` to substitute one Git object with another, but the two objects have different types. Git's internal database stores four types of objects: commits (snapshots with metadata), trees (directory structures), blobs (file contents), and tags (named references). When you run `git replace <original> <replacement>`, Git expects both objects to be of the same type. For example, you can replace a commit with another commit, or a tree with another tree, but by default you cannot replace a commit with a blob. This type enforcement exists because Git internally looks up objects by their hash ID, and the replacement must work correctly in the same context as the original. A function expecting a commit object would fail if it received a tree object instead. However, Git does allow you to bypass this restriction using the `-f` (force) flag when you have a specific use case that requires cross-type replacement.

Typical symptoms

  • Running git replace <hash1> <hash2> fails with 'fatal: Objects must be of the same type to be replaced'
  • Attempting to create a replacement reference between objects of different types is rejected
  • Commands like git replace --edit fail when the result would be a different object type
  • Scripts or automation using git replace fail unexpectedly when object types don't match

Common causes

  1. Attempting to replace a commit object with a tree, blob, or tag object (or vice versa)
  2. Using incorrect object references that resolve to different types than expected
  3. Copying a hash from git log (commit) when you meant to use a tree or blob hash
  4. Misunderstanding the difference between a commit and its associated tree object
  5. Using git replace --edit and accidentally changing the object type during editing

How to fix "fatal: Objects must be of the same type to be replaced"

1Identify the types of both objects

First, determine the type of each object you're trying to use:

bash
# Check the type of the original object
git cat-file -t <original-hash>

# Check the type of the replacement object
git cat-file -t <replacement-hash>

This will output one of: commit, tree, blob, or tag. Both must match for the replacement to work without forcing.

2Use the -f flag to force replacement (if intentional)

If you specifically need to replace objects of different types, use the -f or --force flag:

bash
git replace -f <original-hash> <replacement-hash>

Warning: Forcing a type mismatch can cause unexpected behavior. Git commands that expect a specific object type may fail or produce incorrect results when they encounter the replacement. Only use this when you fully understand the implications.

3Find the correct object of the same type

If you accidentally used the wrong hash, find the correct one:

For commits:

bash
# Find commit hashes in the log
git log --oneline

# Get the full commit hash
git rev-parse <commit-ref>

For trees (directory snapshots):

bash
# Get the tree object from a commit
git rev-parse <commit>^{tree}

# Or view tree contents
git ls-tree <commit>

For blobs (file contents):

bash
# Get blob hash for a specific file at a commit
git rev-parse <commit>:<path/to/file>

# List blobs in current tree
git ls-tree -r HEAD
4Replace commit with another commit

The most common use case is replacing one commit with another:

bash
# Replace an old commit with a corrected version
git replace <old-commit-hash> <new-commit-hash>

# Verify the replacement was created
git replace -l

# Check that the replacement is in effect
git log --oneline

This is useful for correcting commit messages, author information, or parent references without rewriting history.

5Replace a tree to modify directory structure

To replace a tree object (for example, to modify a directory structure in history):

bash
# Get the tree hash from the commit you want to modify
git rev-parse <commit>^{tree}

# Create a new tree with modifications (example using git mktree)
# Then replace the original tree
git replace <original-tree-hash> <new-tree-hash>

This approach modifies how a directory appears at a specific point in history without changing the commit hashes.

6Use git replace --edit for same-type modifications

The --edit option creates a replacement of the same type after allowing you to edit:

bash
# Edit a commit (opens editor with commit data)
git replace --edit <commit-hash>

# Edit a blob
git replace --edit <blob-hash>

This is the safest approach as Git automatically ensures the replacement is the same type as the original.

7List and manage existing replacements

View and manage your replacement references:

bash
# List all replacement refs
git replace -l

# Show details about a specific replacement
git replace -l <original-hash>

# Delete a replacement
git replace -d <original-hash>

Replacements are stored in refs/replace/ and can be pushed/fetched like other refs:

bash
# Push replacement refs to remote
git push origin 'refs/replace/*'

# Fetch replacement refs from remote
git fetch origin 'refs/replace/*:refs/replace/*'

Advanced notes

### Understanding Git Object Types

Git has exactly four object types:

- Commit: Contains metadata (author, date, message), a pointer to a tree, and pointers to parent commits
- Tree: Represents a directory listing with names and pointers to blobs or other trees
- Blob: Stores file content (just the data, no filename or permissions)
- Tag: An annotated tag with metadata pointing to another object (usually a commit)

The type restriction exists because each object type has a specific structure that Git commands expect. Replacing a commit with a blob would break commands like git log that need to traverse parent pointers.

### When Force Replacement Makes Sense

There are rare legitimate cases for forcing type mismatches:

- Replacing a lightweight tag ref with an annotated tag object
- Advanced repository surgery where you understand the consequences
- Experimental workflows with custom tooling that handles mixed types

### Disable Replacements Temporarily

If replacements are causing issues, you can disable them:

bash
# Disable replacements for a single command
git --no-replace-objects log

# Disable replacements via environment variable
export GIT_NO_REPLACE_OBJECTS=1

### Replacement Refs Storage

Replacements are stored as refs in .git/refs/replace/<original-sha>. Each ref file contains the SHA of the replacement object. You can manually inspect these:

bash
# View replacement refs directly
ls .git/refs/replace/

# See what a replacement points to
cat .git/refs/replace/<original-sha>

### Alternative: Use git filter-repo

For complex history modifications, consider git filter-repo instead of git replace:

bash
# Install git-filter-repo
pip install git-filter-repo

# Rewrite history (creates new commits)
git filter-repo --commit-callback 'commit.message = commit.message.replace(b"old", b"new")'

Unlike replacements, filter-repo actually rewrites history creating new objects, which may be more appropriate for permanent changes.

Frequently asked questions

What does "fatal: Objects must be of the same type to be replaced" mean?
The error "fatal: Objects must be of the same type to be replaced" occurs when you attempt to use git replace to substitute one Git object with another, but the two objects have different types. Git's internal database stores four types of objects: commits (snapshots with metadata), trees (directory structures), blobs (file contents), and tags (named references). When you run git replace <original> <replacement>, Git expects both objects to be of the same type.
How do I fix "fatal: Objects must be of the same type to be replaced"?
This Git error occurs when using git replace to substitute one object with another of a different type. Use the -f flag to force the replacement, or ensure both objects share the same type (commit, tree, blob, or tag).
What causes "fatal: Objects must be of the same type to be replaced"?
Attempting to replace a commit object with a tree, blob, or tag object (or vice versa) Using incorrect object references that resolve to different types than expected Copying a hash from git log (commit) when you meant to use a tree or blob hash
Is the "fatal: Objects must be of the same type to be replaced" error serious?
It is a low-severity error โ€” more of a blocker than a risk. The steps above resolve it.

Official resources & further reading