Compatibility
Minecraft: Java Edition
Platforms
Links
Tags
Creators
Details
GitPull
GitPull 1.4 is a Git-based datapack updater for Spigot/Paper. Players can pull repositories, follow progress in chat, and click a message to reload datapacks after an update. GitHub push notifications are integrated through a separate Webhook service and local event files.
Features
- Run
git pullorgit cloneagainst the configured URL, without configuringorigin. - Support multiple repositories, branches, HTTP proxies, and execution timeouts.
- Run Git asynchronously and show the repository, Git stage, percentage, and elapsed time.
- Distinguish updates, already-up-to-date results, failures, and timeouts.
- Provide a configurable success sound and a clickable datapack reload action.
- Notify online operators or players with
gitpull.notifyafter a successful Webhook pull.
Installation and upgrades
Requirements: Java 21 or later, a Spigot/Paper server supporting api-version: 1.21, and Git installed on the server. The project compiles against Spigot API 1.21.11.
Build from the project directory:
.\gradlew.bat build
On Linux/macOS, use ./gradlew build. The artifact is build/libs/gitpull-1.4.jar.
- Copy the JAR into the server's
pluginsdirectory and start the server. - Edit the generated
plugins/gitpull/config.yml, replacing the example repository URL, directory, and branch. - Run
/pull reloadto apply the configuration, then/pull <repository-name>.
To upgrade, stop the server and replace the old JAR, keeping the configuration directory. If the server has settings.update-folder: update configured, you can instead place the new JAR in plugins/update/ under the same filename as the old JAR. It will replace the old file on the next startup. Keep only one GitPull JAR in the plugin directory.
/pull reload rereads configuration. Running Git tasks retain the repository settings they started with. A JAR upgrade requires a server restart.
Commands and permissions
| Command | Purpose | Permission |
|---|---|---|
/pull |
Pull all valid repositories in configuration order | gitpull.pull |
/pull <name> |
Pull one repository; repository names support tab completion | gitpull.pull |
/pull reload |
Reload configuration and the notification listener | gitpull.pull, gitpull.reload |
These permissions default to operators. The console can also run the commands. The repository name reload is reserved.
| Notification permission | Purpose |
|---|---|
gitpull.notify |
Receive Webhook notifications; granted to operators by default |
minecraft.command.reload |
Display and execute the datapack reload action; operators also see the action |
The action runs /minecraft:reload as the player, and the server still checks command permissions. It reloads datapacks, not plugin JARs. The in-game link is currently labeled 重载数据包 (Reload datapacks); plugin messages are in Chinese.
Configuration
git-command: git
http-proxy: ""
clone-if-missing: true
timeout-seconds: 300
notifications:
sound:
enabled: true
id: "minecraft:entity.experience_orb.pickup"
volume: 0.8
pitch: 1.2
webhook-notifications:
enabled: true
directory: "webhook-events"
max-age-seconds: 300
repositories:
pack:
repository: "https://github.com/OWNER/REPO.git"
directory: "world/datapacks/my-pack"
branch: "main"
| Setting | Meaning |
|---|---|
git-command |
Git executable name or full path, such as /usr/bin/git |
http-proxy |
Sets uppercase and lowercase HTTP/HTTPS proxy environment variables for Git subprocesses. An empty value adds no overrides; inherited environment variables and Git configuration may still apply. SSH URLs do not use this HTTP proxy |
clone-if-missing |
Allow cloning when the target does not exist, or is empty and has no Git repository |
timeout-seconds |
Git operation timeout per repository, with a minimum of 1 second |
repositories.<name>.repository |
HTTPS or SSH URL used for both cloning and pulling; existing remote configuration is preserved |
repositories.<name>.directory |
Absolute path, or a path relative to the server's world container, normally the server root |
repositories.<name>.branch |
Remote branch to clone or pull. Empty means the remote default branch; pulling does not switch the local branch |
webhook-notifications.enabled |
Listen for local event files; can be disabled for manual-only use |
webhook-notifications.directory |
Event directory; relative paths resolve against plugins/gitpull, and absolute paths are supported |
webhook-notifications.max-age-seconds |
Maximum notification age, default 300 seconds, configurable from 1 to 86400 seconds |
Private repositories use the SSH keys or HTTPS credentials of the OS account running the game server. Confirm that this account can access the repository without interactive prompts.
Progress, sound, and datapack reload
When Git emits stage and percentage information, chat progress updates at most once per second. With no new progress, the plugin reports the current status and elapsed time every 10 seconds. Percentages describe the current Git stage, not overall task completion.
- Manual pulls: when every repository succeeds and at least one repository is updated or cloned, the requester receives one sound and the final message offers the reload action.
- Webhook pulls: each revision change plays a sound for notification recipients and offers the reload action to players with reload permission.
- Already-up-to-date results display text only. Failures and timeouts do not play a success sound.
notifications.sound controls the enabled flag, namespaced sound ID, volume from 0.0–1.0, and pitch from 0.5–2.0. The default is the experience orb pickup sound. Another valid choice is minecraft:entity.ender_dragon.death. The client must have the selected sound; playback uses the Players sound category. Apply changes with /pull reload.
GitHub Webhook setup
How it works
GitHub push → HTTPS endpoint → webhook service → pull-script.sh
↓ successful Git pull
gitpull-notify.py
↓ event file
plugins/gitpull/webhook-events
↓ polled every 40 ticks
chat, sound, reload action
GitPull does not expose an HTTP endpoint. Setting webhook-notifications.enabled: true enables file monitoring; you must also deploy a service to receive GitHub requests and a script to publish notifications. Manual /pull commands launch Git directly and do not use Webhook.
This example uses Linux, adnanh/webhook 2.8+, Nginx, and systemd. It assumes an existing game-server OS account named minecraft, a server root of /srv/minecraft, repository name pack, and branch main. Substitute your actual values. Webhook and the game server use the same account and filesystem.
1. Install dependencies and scripts
On Debian/Ubuntu, install the dependencies, then copy the scripts from this project's directory:
sudo apt install git python3 webhook nginx util-linux coreutils
sudo install -d -o minecraft -g minecraft /srv/gitpull
sudo install -d -o minecraft -g minecraft /srv/minecraft/plugins/gitpull/webhook-events
sudo install -o minecraft -g minecraft -m 750 deploy/pull-script.sh /srv/gitpull/pull-script.sh
sudo install -o minecraft -g minecraft -m 640 deploy/gitpull-notify.py /srv/gitpull/gitpull-notify.py
sudo sed -i 's/\r$//' /srv/gitpull/pull-script.sh /srv/gitpull/gitpull-notify.py
Python 3.8 or later is required. util-linux provides flock; coreutils provides timeout. Event files are readable and writable only by their owner, so this setup runs Webhook and the game server as the same account.
The bundled pull-script.sh and config-tokumei.yml contain paths specific to the tokumei deployment. For another environment, edit /srv/gitpull/pull-script.sh:
| Script location | Value for this example |
|---|---|
Lock file after exec 9> |
/srv/gitpull/pull.lock |
Directory after cd |
/srv/minecraft/world/datapacks/my-pack |
URL and branch passed to git pull |
https://github.com/OWNER/REPO.git main |
-c http.proxy=... |
Set your proxy, or remove this argument if no proxy is needed |
Script path after python3 |
/srv/gitpull/gitpull-notify.py |
| Notification directory argument | /srv/minecraft/plugins/gitpull/webhook-events |
Notification repository-name argument tokumei |
pack, matching the plugin configuration for display in chat. Notification names must contain 1–80 ASCII letters, digits, _, ., or - |
The resulting notification call should be:
python3 /srv/gitpull/gitpull-notify.py /srv/minecraft/plugins/gitpull/webhook-events pack "$status" "$before" "$after"
The pull script requires an existing Git repository. Clone it using the plugin or manually as minecraft into the target directory. The bundled script uses proxy 192.168.6.2:7890 and a 120-second timeout. The plugin's http-proxy and timeout-seconds settings do not change this script.
2. Configure the Webhook endpoint
Save this as /srv/gitpull/hooks.json, replacing REPLACE_WITH_YOUR_SECRET with your own random secret. This configuration accepts signed pushes to main:
[
{
"id": "gitpull",
"execute-command": "/srv/gitpull/pull-script.sh",
"command-working-directory": "/srv/gitpull",
"http-methods": ["POST"],
"trigger-rule": {
"and": [
{"match": {"type": "payload-hmac-sha256", "secret": "REPLACE_WITH_YOUR_SECRET", "parameter": {"source": "header", "name": "X-Hub-Signature-256"}}},
{"match": {"type": "value", "value": "push", "parameter": {"source": "header", "name": "X-GitHub-Event"}}},
{"match": {"type": "value", "value": "refs/heads/main", "parameter": {"source": "payload", "name": "ref"}}},
{"match": {"type": "value", "value": "false", "parameter": {"source": "payload", "name": "deleted"}}}
]
}
}
]
Make the file readable by minecraft, for example with sudo chown minecraft:minecraft /srv/gitpull/hooks.json and sudo chmod 600 /srv/gitpull/hooks.json.
This example responds immediately after accepting a request. Git results go to the service log and event files. See the official Webhook field reference.
Create /etc/systemd/system/gitpull-webhook.service:
[Unit]
Description=GitPull Webhook
After=network-online.target
Wants=network-online.target
[Service]
User=minecraft
Group=minecraft
WorkingDirectory=/srv/gitpull
ExecStart=/usr/bin/webhook -ip 127.0.0.1 -port 9000 -hooks /srv/gitpull/hooks.json -hotreload -verbose
Restart=on-failure
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now gitpull-webhook
If you already run Webhook, add the hook to its existing hooks array instead of starting another process on the same port. Restart that service if you change its systemd startup arguments.
3. Set up HTTPS
Point your domain at the server and obtain a valid TLS certificate. Add and enable an Nginx site, replacing the domain and certificate paths:
server {
listen 443 ssl;
server_name hooks.example.com;
ssl_certificate /etc/letsencrypt/live/hooks.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/hooks.example.com/privkey.pem;
location = /hooks/gitpull {
proxy_pass http://127.0.0.1:9000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
sudo nginx -t
sudo systemctl reload nginx
Allow incoming HTTPS on port 443. Webhook listens only on localhost port 9000.
4. Configure the GitHub repository
Open Settings → Webhooks → Add webhook in the repository:
| Field | Value |
|---|---|
| Payload URL | https://hooks.example.com/hooks/gitpull |
| Content type | application/json |
| Secret | The same secret as in hooks.json |
| SSL verification | Enabled |
| Events | Just the push event |
| Active | Enabled |
You need permission to manage repository webhooks. Use gitpull consistently for the hook ID and the endpoint suffix in GitHub and Nginx. If you change branches, update the script, plugin configuration, and refs/heads/main filter together.
5. Enable in-game notifications and verify
Set the plugin configuration to:
webhook-notifications:
enabled: true
directory: "webhook-events"
max-age-seconds: 300
This resolves to /srv/minecraft/plugins/gitpull/webhook-events and must match the Python writer's directory. Run /pull reload, join the game as an operator, and push a text file outside datapack resources to main.
Check the service log:
sudo journalctl -u gitpull-webhook -n 50 --no-pager
An update produces AUTOPULL_RESULT UPDATED <old-revision> <new-revision>; no change produces AUTOPULL_RESULT UNCHANGED <revision>. The plugin normally sends the notification within about 2 seconds and deletes the event file afterward. Delete and push the test file once verification is complete to check a second notification.
Known limitations and troubleshooting
- Concurrent Webhook and manual pulls: the script's
flockcoordinates only Webhook scripts. The plugin prevents concurrent plugin tasks, but the two paths do not share a lock. Avoid running both against the same repository at once; Git lock conflicts or failed pulls can occur. - Webhook failure notifications: only successful updates and already-up-to-date results produce event files. Check Webhook logs for failures, timeouts, and busy results. HTTP 200 only acknowledges the request.
- No in-game notification: check that the plugin is loaded, event paths match, the service account can read and write them, and the player is an operator or has
gitpull.notify. Expired events are deleted; malformed files are renamed with.invalid. If no eligible player is online, the event is logged and consumed without replaying it on login. - No sound or reload action: already-up-to-date results provide neither. The action requires reload permission; manual batches also require all repositories to succeed. Client audio settings and sound resources determine whether playback is audible.
- Files updated but gameplay unchanged: GitPull does not automatically reload datapacks. Click the reload action or run
/minecraft:reload. This reloads enabled datapacks, not just the updated repository. - Directory or authentication errors: cloning will not overwrite a nonempty directory that is not a Git repository. Configure private repository credentials for the account actually running the script or game server.
- Other deployment limits: the bundled Webhook scripts target Linux and one repository. GitPull's listener consumes files, not remote HTTP callbacks. Separate deployments need a notification directory accessible to both the writer and the plugin.
Development checks
gradlew build compiles the plugin and runs Java tests. On Linux, test the Webhook script and event writer separately with:
python3 deploy/test_webhook.py "$(pwd)/deploy/pull-script.sh" "$(pwd)/deploy/gitpull-notify.py"
The test uses temporary Git repositories and a separate local Webhook process. It covers updates, unchanged repositories, busy execution, failures, timeouts, and successful event publication.


