| Crates.io | git-next |
| lib.rs | git-next |
| version | 2025.7.1 |
| created_at | 2024-07-14 19:25:04.720125+00 |
| updated_at | 2025-07-06 16:22:11.136923+00 |
| description | trunk-based development manager |
| homepage | |
| repository | https://git.kemitix.net/kemitix/git-next |
| max_upload_size | |
| id | 1303197 |
| size | 1,626,798 |
A source-control branching model, where developers collaborate on code in a single branch called ‘trunk’, resist any pressure to create other long-lived development branches by employing documented techniques. They therefore avoid merge hell, do not break the build, and live happily ever after. - source
git-next is a combined server and command-line tool that enables trunk-based
development workflows where each commit must pass CI before being included in
the main branch.
See Behaviour to learn how we do this.

See .cargo/config.toml for how they are configured.
You can install git-next from https://crates.io/:
cargo install git-next
If you use mise:
mise use -g cargo:git-next
Or you can install git-next from source after cloning:
cargo install --path .
By default, git-next will be built with the following features:
forge-forgejoforge-githubThere are additional features:
notify-emailNote: the additional features are included when building or using the docker images.
git-next uses three branches, main, next and dev, although they do not
need to have those names. In the documentation we will use those names, but
each repo must specify the names of the branches to use for each, even if they
happen to have those same names.
main, next and dev must be specified in either
the .git-next.toml in the repo itself, or in the server configuration file,
git-next-server.toml. See below for details.next branch is pushed.dev branch must have the main branch as an ancestor.next branch must have the main branch as an ancestor.The server is configured by the git-next-server.toml file.
The server should listen for webhook notifications from each forge.
[listen]
http = { addr = "0.0.0.0", port = 8080 }
url = "https://localhost:8080"
The server needs to be able to receive webhook notifications from your forge, (e.g. github.com). You can do this via any method that suits your environment, e.g. ngrok or a reverse proxy from a web server that itself can route traffic to the machine you are running the git-next server on.
Specify the address and port the server should listen to for incoming webhooks. This is the address and port that your reverse proxy should route traffic to.
The HTTPS URL for forges to send webhooks to.
Your forges need to know where they should route webhooks to. This should be an address this is accessible to the forge. So, for github.com, it would need to be a publicly accessible HTTPS URL. For a self-hosted forge, e.g. Forgejo, on your own network, then it only needs to be accessible from the server your forge is running on.
The server should be able to notify the user when manual intervention is required.
[shout]
desktop = true
[shout.webhook]
url = "https//localhost:9090"
secret = "secret-password"
[shout.email]
from = "git-next@example.com"
to = "developer@example.com"
[shout.email.smtp]
hostname = "smtp.example.com"
username = "git-next@example.com"
password = "MySecretEmailPassword42"
When specified as true, desktop notifications will be sent for some events.
Will send a POST request for some events.
See Notifications for more details.
Will send an email for some events.
With just from and to specified, git-next will attempt to send emails
with sendmail if it is configured.
Alternatively, you can use an SMTP relay.
Will send emails using an SMTP relay.
[storage]
path = "./data"
git-next will create a bare clone of each repo that you configure it to
monitor. They will all be created in the directory specified here. This data
does not need to be backed up, as any missing information will be cloned when
the server starts up.
Within the forge tree, specify each forge you want to monitor repos on.
Give your forge an alias, e.g. default, gh, github.
e.g.
[forge.github]
forge_type = "GitHub"
hostname = "github.com"
user = "username"
token = "api-key"
max_dev_commits = 25
Forgejo or GitHubdev and main. Defaults to 25.Generally, the user will need to be able to push to main and to force-push
to next.
For each forge, you need to specify which repos on the forge you want to
monitor. They do not need to be owned by the user, but the user must have
the push and force-push permissions as mentioned above for each of the
repositories.
e.g.
[forge.github.repos]
my-repo = { repo = "owner/repo", branch = "main" }
[forge.github.repos.other-repo]
repo = "user/other"
branch = "master"
main = "master"
next = "ci-testing"
dev = "trunk"
Note that toml allows specifying the values on one line, or across multiple
lines. Both are equivalent. What is not equivalent between my-repo and
other-repo, is that one will require a configuration file within the repo
itself. other-repo specifies the main, next and dev branches to be
used, but my-repo doesn't.
A sample .git-next-toml file that would need to exist in my-repo's owner/repo
repo, on the main branch:
[branches]
main = "main"
next = "next"
dev = "dev"
.git-next.toml file if neededmainnextdevUp to version 2025.3.4, you could specify an existing git repository using
the gitdir property for a repo. This has been removed, and now git-next
will clone and manage it's own copy of each repo.
When sending a Webhook Notification to a user they are sent using the Standard Webhooks format. That means all POST messages have the following headers:
Webhook-IdWebhook-SignatureWebhook-TimestampThis message type indicates that the dev branch is not based on main.
Action Required: Rebase the dev branch onto the main branch.
Sample payload:
{
"data": {
"branches": {
"dev": "dev",
"main": "main"
},
"forge_alias": "jo",
"repo_alias": "kxio",
"log": [
"* 9bfce91 (origin/dev) fix: add log graph to notifications",
"| * c37bd2c (origin/next, origin/main) feat: add log graph to notifications",
"|/",
"* 8c19680 refactor: macros use a more common syntax"
]
},
"timestamp": "1721760933",
"type": "branch.dev.not-on-main"
}
This message type indicates that the commit on the tip of the next branch has failed the
configured CI checks.
Action Required: Either update the commit to correct the issue CI raised, or, if the issue is transient (e.g. a network issue), re-run/re-start the job in your CI.
Sample payload:
{
"data": {
"commit": {
"sha": "c37bd2caf6825f9770d725a681e5cfc09d7fd4f2",
"message": "feat: add log graph to notifications (1 of 2)"
},
"forge_alias": "jo",
"repo_alias": "kxio",
"log": [
"* 9bfce91 (origin/dev) feat: add log graph to notifications (2 of 2)",
"* c37bd2c (origin/next) feat: add log graph to notifications (1 of 2)",
"* 8c19680 (origin/main) refactor: macros use a more common syntax"
]
},
"timestamp": "1721760933",
"type": "cicheck.failed"
}
This message type indicates that git-next wasn't able to load the configuration for the
repo from the git-next.toml file in the repository.
Action Required: Review the reason provided.
Sample payload:
{
"data": {
"reason": "File not found: .git-next.toml",
"forge_alias": "jo",
"repo_alias": "kxio"
},
"timestamp": "1721760933",
"type": "config.load.failed"
}
This message type indicates that git-next wasn't able to register it's webhook with the
forge repository, so will not receive updates when the branches in the repo are updated.
Action Required: Review the reason provided.
Sample payload:
{
"data": {
"reason": "repo config not loaded",
"forge_alias": "jo",
"repo_alias": "kxio"
},
"timestamp": "1721760933",
"type": "webhook.registration.failed"
}
Implementation Note: git-next uses Rust's git2 library with libgit2 under the hood rather than requiring a system git installation. This makes behavior more consistent across platforms.
The branch names are configurable, but we will talk about main, next and dev.
Development happens on the dev branch, where each commit is expected to
be able to pass the CI checks.
(Note: in the diagrams, mermaid isn't capable of showing main and next on
the same commit, so we show next as empty)
gitGraph
commit
commit
branch next
branch dev
commit
commit
commit
When the git-next server sees that the dev branch is ahead of the next
branch, it will push the next branch fast-forward one commit along the dev
branch.
gitGraph
commit
commit
branch next
commit
branch dev
commit
commit
It will then wait for the CI checks to pass for the newly updated next branch.
When the CI checks for the next branch pass, it will push the main branch
fast-forward to the next branch. We return to the top and start again.
gitGraph
commit
commit
commit
branch next
branch dev
commit
commit
If the CI checks should fail for the next branch, the developer should
amend that commit in the history of their dev branch.
They should then force-push their rebased dev branch.
gitGraph
commit
commit
branch next
commit
checkout main
branch dev
commit
commit
commit
git-next will then detect that the next branch is no longer part of the
dev branch ancestry, and will reset next back to main.
We then return to the top, where git-next sees that dev is ahead of next.
When the dev branch is on the same commit as the main branch, then there
are no pending commits and git-next will wait until it receives a webhook
indicating that there has been a push to one of the branches. At which point
it will start at the top again.
The dev branch should have the next branch as an ancestor.
However, when the commit on tip of the next branch has failed CI and is
amended, this will not be the case. When this happens git-next will
force-push the next branch back to the same commit as the main branch.
This is the only time a force-push will happen in git-next.
In short, the next branch belongs to git-next. Don't try to update it
yourself. git-next will update the next it as it sees fit.
To use git-next for trunk-based development, follow these steps:
You need to specify which branches you are using. You can do this in the repo, or in the server configuration.
To create a default config file for the repo, run this command in the root of your repo:
git next init
This will create a .git-next.toml file. Default
By default the expected branches are main, next and dev. Each of these
three branches must exist in your repo.
The server uses the file git-next-server.toml for configuration. It expects
to find this file in the current directory when executed.
The create the default config file, run this command:
git next server init
This will create a git-next-server.toml file. Default
Edit this file to your needs. See the Configuration section above.
In the directory with your git-next-server.toml file, run the command:
git next server start
The following forges are supported:
Note: Forgejo is a hard fork of Gitea, but currently they are largely compatible.
For now using a forge_type of Forgejo with a Gitea instance will probably work
okay. The only API calls we make are around registering and unregistering webhooks.
So, as long as those APIs remain the same, they should be compatible.
Configure the forge in git-next-server.toml like:
[forge.jo]
forge_type = "Forgejo"
hostname = "git.myforgejo.com"
user = "bob"
token = "..."
[forge.jo.repos]
hello = { repo = "user/hello", branch = "main" } # maps to https://git.example.net/user/hello on the branch 'main'
world = { repo = "user/world", branch = "master", main = "master", next = "upcoming", "dev" = "develop" } # maps to the 'master' branch
The token is created on your Forgejo instance at (for example)
https://git.myforgejo.com/user/settings/applications
and requires the write:repository permission.
Configure the forge in git-next-server.toml like:
[forge.gh]
forge_type = "GitHub"
hostname = "github.com" # required even for GitHub
user = "bob"
token = "..."
[forge.gh.repos]
hello = { repo = "user/hello", branch = "main" } # maps to https://github.com/user/hello on the branch 'main'
world = { repo = "user/world", branch = "master", main = "master", next = "upcoming", "dev" = "develop" } # maps to the 'master' branch
The token is created here and requires the repo and admin:repo_hook permissions.
git-next is available as a Docker image.
docker pull docker pull git.kemitix.net/kemitix/git-next:latest
Here is an example docker-compose.yml:
services:
server:
image: git.kemitix.net/kemitix/git-next:latest
container_name: git-next-server
restart: unless-stopped
environment:
RUST_LOG: "hyper=warn,info"
ports:
- 8080:8092
volumes:
- ./:/app/
Note: this assumes the git-next-server.toml has a listen.http.port of
8092 and that you are using a reverse proxy to route traffic arriving at
listen.url to port 8080.
This will run with the server start options:
docker run -it -p "8080:8092" -v .:/app/ git.kemitix.net/kemitix/git-next:latest
To perform server init:
docker run -it -v .:/app/ git.kemitix.net/kemitix/git-next:latest server init
To perform repo init:
docker run -it -v .:/app/ git.kemitix.net/kemitix/git-next:latest init
TUI support is not available in the docker container. See kemitix/git-next#154.
Contributions to git-next are welcome! If you find a bug or have a feature
request, please
create an issue.
If you'd like to contribute code, feel free to submit changes.
Before you start committing, run the just install-hooks command to setup the
Git Hooks. (Get Just)
mindmap
Root
Alerts
FileWatcher
Server
Repo 1
Repo 2
git-next is released under the MIT License.