This Git error occurs when you try to rebase while having staged changes in your index that haven't been committed. Git prevents the rebase to protect your staged work from being lost. The solution is to commit your staged changes, stash them, or use the --autostash flag.
This error appears when you attempt to run `git rebase` while having changes that have been staged (added to the index with `git add`) but not yet committed. Git refers to this state as having a "dirty index" or "dirty worktree." The key distinction is that these are **staged changes**, meaning you've already run `git add` on the files, but haven't completed the commit. Git is protecting you because a rebase operation needs to manipulate commits and potentially modify your working directory, which could interfere with or lose your carefully staged changes. During a rebase, Git checks out different commits and applies your branch's commits on top of another branch. If you have uncommitted staged changes, these would be in a limbo state - not part of any commit, but also not simply working directory changes that could be easily set aside. Git enforces a clean index to ensure the rebase can proceed safely and be cleanly aborted if needed.
First, identify what Git is referring to by checking your staged changes:
# View full status showing staged and unstaged changes
git status
# You'll see output like:
# Changes to be committed:
# (use "git restore --staged <file>..." to unstage)
#
# modified: src/app.js
# new file: src/utils.jsTo see the actual content of staged changes:
# Show diff of staged (cached) changes
git diff --cached
# Or equivalently
git diff --staged
# Show diff for a specific staged file
git diff --cached src/app.jsIf your staged changes are ready to be part of your Git history, the simplest solution is to commit them:
# Commit the staged changes
git commit -m "Your descriptive commit message"
# Now the rebase will work
git rebase mainIf you're not sure about the commit message or want to review first:
# Opens your editor with the diff shown
git commit -v
# Quick work-in-progress commit
git commit -m "WIP: description of changes"Tip: If you need to clean up this commit later, you can amend it or use interactive rebase to squash it:
# Amend the last commit (if you haven't pushed)
git commit --amend
# Or squash during a later rebase
git rebase -i HEAD~2If you want to temporarily set aside your changes without committing:
# Stash all changes including staged ones
git stash
# Now perform the rebase
git rebase main
# After rebasing, restore your stashed changes
git stash popImportant: By default, git stash stashes both staged and unstaged changes, but when you pop, everything comes back as unstaged. To preserve the staged state:
# Stash keeping the index (staged changes) separate
git stash --keep-index
# Or stash everything and restore with index intact
git stash
git rebase main
git stash pop --indexThe --index flag with pop tries to restore the staged/unstaged state as it was before stashing.
Git 2.9+ includes the --autostash flag that automatically handles uncommitted changes:
# Rebase with automatic stashing
git rebase --autostash main
# For pull with rebase
git pull --rebase --autostash
# For interactive rebase
git rebase -i --autostash HEAD~3To make autostash the default behavior:
# Enable autostash for all rebases
git config --global rebase.autoStash true
# Now regular rebase commands will autostash
git rebase main # Autostash happens automaticallyWith autostash enabled, Git automatically creates a stash before rebasing and applies it afterward, making the workflow seamless.
If you decide you don't want the changes staged right now but want to keep them as working directory changes:
# Unstage all files (keep changes in working directory)
git restore --staged .
# Or the older syntax
git reset HEAD
# Unstage specific files
git restore --staged src/app.js
git reset HEAD src/app.jsAfter unstaging, you'll still have the error because now you have unstaged changes. You can then stash those:
git restore --staged .
git stash
git rebase main
git stash popThis gives you more control over how the changes are handled during and after the rebase.
If you've determined the staged changes are not needed:
# Unstage and discard changes for specific files
git restore --staged src/app.js
git restore src/app.js
# Or using reset
git checkout HEAD -- src/app.js
# Discard ALL staged and unstaged changes (DANGEROUS)
git reset --hard HEADWarning: git reset --hard permanently discards all uncommitted changes (both staged and unstaged). Make absolutely sure you don't need these changes before running this command.
To see what you're about to discard:
# Review staged changes before discarding
git diff --cached
# Review unstaged changes
git diff### Understanding Git's Index (Staging Area)
Git has three main areas where file changes can exist:
| Area | Description | Check Command |
|------|-------------|---------------|
| Working Directory | Files as they exist on disk | git diff |
| Index (Staging Area) | Changes marked for next commit | git diff --cached |
| Repository | Committed snapshots | git log |
The error "Your index contains uncommitted changes" specifically refers to the staging area - changes that have been git added but not committed.
### Why Git Blocks Rebase with a Dirty Index
During a rebase, Git:
1. Saves your current branch's commits
2. Resets to the target branch
3. Replays your commits one by one
4. Each replay may modify files in your working directory
If you have staged changes that aren't committed, Git can't safely:
- Determine which commit they should belong to
- Preserve them if a conflict occurs
- Roll back cleanly if you abort the rebase
### The Autostash Mechanism
When using --autostash, Git:
1. Creates a stash entry before starting
2. Performs the rebase
3. Applies the stash afterward
If applying the stash causes conflicts, you'll need to resolve them manually. The stash is kept if the apply fails:
# Check if stash still exists after failed apply
git stash list
# Resolve conflicts in files, then
git stash drop### Preserving Staged State Through Stash
Regular git stash pop returns everything as unstaged changes. To preserve what was staged:
# Pop with index flag to preserve staged state
git stash pop --index
# If that fails due to conflicts
git stash apply --index
# Resolve conflicts
git stash drop### Partial Staging Considerations
If you've used git add -p to stage only some changes in a file, be aware:
- The stash will save both staged and unstaged portions
- stash pop --index will try to restore both states
- Conflicts may arise if the file changed during rebase
### Best Practices to Avoid This Error
1. Commit before switching context: Before rebasing, pull, or other operations, commit your staged changes
2. Use feature branches: Keep work isolated so rebasing is cleaner
3. Configure autostash globally: git config --global rebase.autoStash true
4. Review status habitually: Run git status before rebase operations
5. Use atomic commits: Small, complete commits reduce the chance of having uncommitted staged work
### Difference from "Unstaged Changes" Error
Git has two similar errors:
- "Your index contains uncommitted changes": Staged changes exist (this article)
- "You have unstaged changes": Modified files not staged
Both block rebase, but they refer to different states. Check git status to see which applies to your situation.
warning: BOM detected in file, this may cause issues
UTF-8 Byte Order Mark (BOM) detected in file
fatal: Server does not support --shallow-exclude
Server does not support --shallow-exclude
warning: filtering out blobs larger than limit
Git partial clone filtering large blobs warning
fatal: Server does not support --shallow-since
Server does not support --shallow-since in Git
kex_exchange_identification: Connection closed by remote host
Connection closed by remote host when connecting to Git server