A small fish shell script for Minecraft modpack developers who keep their config, kubejs, or other folders mirrored into a GitHub repo. It syncs your live/dev folders into the repo, shows you what changed, and walks you through committing (optionally splitting changes into multiple commits with their own messages) before pushing.
- fish shell
gitandrsyncinstalled- A local clone of your modpack's GitHub repo
- Clone or download this tool.
- Copy
config.example.fishtoconfig.fish:cp config.example.fish config.fish - Edit
config.fishwith your own paths, pack name, and (optionally) credits and a version string. EachSYNC_FOLDERSentry needs asource:destinationformat — the script checks this at startup and will tell you if an entry is malformed. - Make the script executable:
chmod +x commit.fish - (Optional) Move both files somewhere permanent, like
~/.local/bin/pack-commit/, and add that folder to yourPATHso you can run it from anywhere.
Run it:
./commit.fishOptions:
-h,--help— show usage info and exit--dry-run— show what would be synced and what changed, without committing or pushing anything--stats— show a summary of your logged commit history (total logged, this month, first/most recent) and exit--status— show your current branch, any unpushed commits, and any uncommitted changes already in the repo, without syncing or prompting for anything
What happens when you run it:
- If a previous run was interrupted mid-rebase, it detects that immediately and tells you to resolve it (
git rebase --continueorgit rebase --abort) before doing anything else. - It shows your current branch as a quick sanity check before anything happens, along with a "Last synced" line if a previous push has been logged (relative time plus the exact timestamp).
- If you have commits sitting locally from a previous run that never got pushed (e.g. you answered "n" to the push prompt last time), it shows you exactly what's pending — commit summaries and which files changed — and lets you:
- push them now
- skip (they'll show up again next run)
undothe last one (kept staged, not lost) if you want to redo itamendthe last one's message if only the wording was wrong
- It then syncs your configured folders and shows you what changed (
git status --short). - If nothing changed, it doesn't just exit — it offers to check again right there: type
rto re-sync and check for changes,helpfor a quick reminder, or press Enter to close. Handy if you're editing files with the script's terminal left open, so you don't need to relaunch it from scratch every time. - If something changed, it asks how many commits you want to split the changes into (type
helpat this prompt for a quick reminder, orrto re-sync your folders and re-check for changes — handy if source files are still being written when you reach this point, e.g. a game or launcher still saving on exit). Invalid input here gets a clear rejection message rather than being silently accepted, and if only a single file has changed, you're restricted to 1 commit (still free to typer/help) since splitting one file across multiple commits doesn't make sense. Any files left staged from outside this run are unstaged first, so each commit round only ever contains what you actually specify for it.- For a single commit (the default), it stages everything and asks for one message.
- For multiple commits, instead of typing file paths, you get a numbered list of remaining changed files (aligned consistently even past 9 entries) — just type the numbers you want (e.g.
1 3), space-separated. Press Enter with no numbers to sweep up everything remaining into that commit. Invalid input re-prompts you instead of silently defaulting. - At the commit message prompt: type
historyto reuse one of your last 5 logged messages, orskipto bail out of that specific round entirely without committing anything for it. - A round only counts toward the final push if
git commitactually created a commit — if nothing was staged for that round, it's skipped rather than falsely counted.
- Before pushing, it shows the branch you're pushing to and asks for confirmation — same
undo/amendoptions are available here too, for commits made during this run. - Pushes once at the end (auto-rebasing on top of any remote changes first) and shows a summary of what was actually pushed, plus an aggregate diffstat (total files/insertions/deletions across every commit made this run — accurate even if you used
undo,amend, orskipalong the way) and how long the whole run took.
Every successful push (including pending ones pushed on a later run) is appended to logs/pack-commit.log, next to the script, with a timestamp, pack name, and the folder tag for that commit. This folder is gitignored by default so it stays local to your machine.
If you'd rather double-click an icon than open a terminal manually, create a .desktop file:
[Desktop Entry]
Type=Application
Name=Pack Commit
Exec=konsole -e fish -c "~/.local/bin/pack-commit/commit.fish"
Icon=utilities-terminal
Terminal=falseSwap konsole for your terminal of choice if you're not on KDE. You may need to right-click the file → Properties → allow execution the first time you use it.
config.fishis gitignored so your personal paths and Discord link never end up committed if you fork/publish this tool.- The sync step uses
rsync -a --delete, which mirrors folders exactly — including removing files from the destination that no longer exist in the source. This is intentional (so deleted configs actually get removed from the repo), but be aware of it. - Before pushing, the script runs
git pull --rebaseautomatically to avoid rejected pushes from diverged branches. If a real conflict comes up, it stops and tells you exactly what to run to resolve it manually. undoandamendonly ever act on the single most recent commit — they won't reach further back into history.