![]()
Git-powered version control for Minecraft Java Edition saves
MineCommit converts Minecraft Java Edition saves into a Git-friendly format. By leveraging Git's mature version control and delta compression algorithms, MineCommit achieves:
rayon, NBT parsing via simdnbt, and Git I/O via gitoxideAny question? Please read FAQ.md or feel free to open an issue.
MineCommit depends on an external git binary for the commit and checkout commands. If Git is not installed, please install Git first.
[!NOTE] Still in development, comming soon.
We provide a GUI build for Windows and Linux. Download the minecommit-gui executable from the GitHub Release page.
The GUI is built with Tauri (Rust backend) + React + shadcn/ui (frontend), providing a WYSIWYG interface for basic backup and restore workflows.
The CLI provides fine-grained control over execution details. You can get it from GitHub Release or build it yourself:
cargo install --path . --bin minecommit
[!NOTE] Building from source requires a recent Rust Nightly toolchain (due to
simdnbt). Install via rustup:rustup toolchain install nightly.
You need to define the following two paths:
$SAVE_DIR): The specific world directory under .minecraft/saves/ (containing level.dat).$GIT_DIR): A bare Git repository to store backup data.For the first backup, create a bare Git repository:
git init --initial-branch main --bare $GIT_DIR
git --git-dir $GIT_DIR config gc.auto 0
git --git-dir $GIT_DIR config core.logAllRefUpdates true
Ensure your Git commit identity is set:
git config user.name
git config user.email
If nothing is displayed, set your global Git identity:
git config --global user.name $YOUR_USER_NAME
git config --global user.email $YOUR_USER_EMAIL
minecommit commit $SAVE_DIR $GIT_DIR --branch main --init --message "Your backup note" --repack
This reads the save at $SAVE_DIR, creates an initial commit on the main branch of the bare repository at $GIT_DIR, and automatically repacks loose objects.
minecommit commit --help
Flatten save and commit to Git
Usage: minecommit commit [OPTIONS] --branch <BRANCH> --message <MESSAGE> <SAVE_DIR> <GIT_DIR>
Arguments:
<SAVE_DIR> Path to your save
<GIT_DIR> Path to the bare Git repository
Options:
-b, --branch <BRANCH> Commit to this branch
-v, --verbose... Increase logging verbosity
--init Commit as initial commit
-q, --quiet... Decrease logging verbosity
-m, --message <MESSAGE> Commit message
--repack Automatically repack loose objects
-p, --extra-patterns <EXTRA_PATTERNS> Glob patterns to additionally include
-i, --ignore-patterns <IGNORE_PATTERNS> Glob patterns to explicit ignore
-h, --help Print help
If $SAVE_DIR already exists, MineCommit will rename it to $SAVE_DIR.bak before restoring.
minecommit checkout $SAVE_DIR $GIT_DIR --commit "main~1"
# Restores to the previous commit on the main branch
minecommit checkout --help
Restore save from commit
Usage: minecommit checkout --commit <COMMIT> <SAVE_DIR> <GIT_DIR>
Arguments:
<SAVE_DIR> Path to your save
<GIT_DIR> Path to the bare Git repository
Options:
-c, --commit <COMMIT> Commit-ish to checkout (commit ID or revision expression, e.g. HEAD~1, branch~2)
-h, --help Print help
Flatten / Unflatten (without Git)
If you want to flatten a save to a plain filesystem directory (without Git integration), use flatten and unflatten:
# Deconstruct save into a flattened format
minecommit flatten $SAVE_DIR $FLATTENED_DIR
# Reconstruct save from the flattened format
minecommit unflatten $SAVE_DIR $FLATTENED_DIR
Utils (debugging)
# Dump chunk NBT data to stdout
minecommit utils chunk $REGION_FILE --chunk-x 0 --chunk-z 0
MineCommit's design is based on a core insight: most of a Minecraft save's volume is concentrated in region/*.mca files, which contain substantial spatial redundancy (duplicate blocks and biomes across chunks) and temporal redundancy (minimal differences between adjacent backups).
MineCommit "flattens" the complex .mca binary format into small, Git-diffable files through a handler pipeline:
| Handler | Input Pattern | Description |
|---|---|---|
ChunkRegionHandler |
**/region/r.*.*.mca |
Splits chunk NBT into per-chunk sections and other data |
EntitiesRegionHandler |
**/entities/r.*.*.mca |
Flattens entity region files |
PoiRegionHandler |
**/poi/r.*.*.mca |
Flattens point-of-interest region files |
GzipNbtHandler |
**/*.dat |
Decompresses and processes Gzip-compressed NBT files |
RawHandler |
user-defined | Copies arbitrary files as-is |
IgnoreHandler |
user-defined | Explicitly ignores matching files |
Each handler operates within its own namespaced workspace. The ODB (Object Database) abstraction layer decouples storage from handler logic, supporting both local filesystem backends (LocalFsOdb) and Git-backed storage (LocalGitOdb) with parallel read/write operations via rayon.
minecommit flatten: Deconstruct save files into a flattened formatminecommit unflatten: Reconstruct save files from the flattened formatminecommit commit: Stream-flatten and commit to Gitminecommit checkout: Checkout from Git and stream-restore the saveChunkRegion, EntitiesRegion, PoiRegion, GzipNbt, Raw, Ignoreminecommit merge: Chunk-level and game-semantic level mergingminecommit diff: Quickly view differences between two commitsminecommit blame: Block-level history trackingThe easiest way to contribute is just using MineCommit. You can use it on your saves during gaming.
If you encounter problems, feel free to open an issue.
For developing guide, please read CONTRIBUTING.md.
Special thanks to the gitoxide project (licensed under MIT / Apache-2.0) for providing a highly efficient and modern Git-compatible implementation.
Thanks to the simdnbt project (licensed under MIT) for providing an extremely impressive NBT serialization/deserialization implementation.
Thanks to Lewis for providing the 4.6 GiB real-world test save. In the early stages of development, we lacked a large amount of real experimental data.
Thanks to everyone who followed this project in its early stages. Your questions and feedback are the fuel that drives this project forward.
Licensed under either of
at your option.
$ claude mcp add minecommit \
-- python -m otcore.mcp_server <graph>