This error occurs when you try to use git mv on a file that Git is not tracking. Either add the file to Git first, or use regular mv followed by git add instead.
The `git mv` command is a convenience wrapper that combines moving/renaming a file with updating Git's index. When you run `git mv source destination`, Git performs three operations under the hood: it moves the file on disk, runs `git rm` on the old path, and runs `git add` on the new path. For this to work, the source file must already be tracked by Git. If the file has never been added to the repository (it's "untracked"), Git cannot record the rename in its history because there's no history to preserve. That's when you see the "fatal: not under version control" error. This commonly happens when you create a new file and immediately try to move it before committing, or when you're working with files that were intentionally left untracked (like build artifacts or local config files). The solution is simple: either track the file first with `git add` and then use `git mv`, or just use the regular `mv` command since there's no Git history to preserve anyway.
First, verify the file's status in Git:
git statusLook for your file. If it appears under "Untracked files:", that's why git mv fails. If it doesn't appear at all, it might be ignored.
To check if a file is tracked:
git ls-files --error-unmatch file.txtIf this returns an error, the file is not tracked.
If you want to preserve Git history (useful if you've already committed the file before), add it first:
git add file.txt
git mv file.txt new-location/file.txtNote: This only works for files that are staged. If you want to track AND move in one go, you'll need to commit first or use Option B.
For files that have never been tracked, there's no Git history to preserve. Just use regular shell commands:
mv file.txt new-location/file.txt
git add new-location/file.txtThis is often the simplest solution. The end result is the same: the file ends up tracked in its new location.
When moving many untracked files, use regular mv with git add --all:
mv *.txt new-directory/
git add --allOr for a more targeted approach:
mv file1.txt file2.txt new-directory/
git add new-directory/Git will figure out they are new files and stage them.
If your file should be tracked but isn't, it might be in .gitignore:
git check-ignore -v file.txtIf this shows a .gitignore rule, you can force-add the file:
git add -f file.txt
git mv file.txt new-location/file.txtOn case-insensitive filesystems, Git might not recognize path differences. If you're renaming with only case changes:
# Two-step rename to work around case sensitivity
git mv file.txt file-temp.txt
git mv file-temp.txt File.txtOr use the force flag (Git 2.0.1+):
git mv file.txt File.txtModern Git handles case-only renames automatically.
If you're moving multiple files and some are untracked, use the -k flag to skip errors:
git mv -k *.txt destination/This will move all tracked .txt files and silently skip any untracked ones. You can then move the untracked files separately with regular mv.
If the destination file already exists and is tracked, git mv will refuse to overwrite it. Use -f to force:
git mv -f source.txt destination.txtCaution: This will overwrite the destination file. Make sure you don't need its contents before using this flag.
### Understanding git mv Internals
git mv is essentially equivalent to:
mv old new
git rm old
git add newGit doesn't actually store renames in its data model. Instead, it uses heuristics to detect renames when you look at history. This means using mv + git add produces the exact same result in terms of Git history as git mv.
### Why Use git mv at All?
1. Convenience: One command instead of three
2. Safety: Won't overwrite destination without -f flag (unlike regular mv)
3. Case-only renames: Better detection of case changes on case-insensitive systems
4. Submodule handling: Properly updates submodule configuration when moving submodules
### Merge Conflict Edge Case
As of Git 2.29, if a file has unresolved merge conflicts, git mv will show the "not under version control" error even though the file is technically tracked. This is a misleading error message. Resolve the merge conflict first:
git status # Check for conflicts
# Resolve conflicts in the file
git add file.txt
git mv file.txt new-location/file.txt### Bulk Operations
For large-scale restructuring, consider using a combination:
# Move tracked files with git mv
git mv src/*.js lib/
# Move remaining untracked files with regular mv
mv src/*.js lib/ 2>/dev/null || true
# Stage everything
git add --all### Dry Run
To preview what git mv would do without making changes:
git mv -n source.txt destination.txtThe -n (or --dry-run) flag shows what would happen.
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