A stack diff poor-man's solution
Project description
git-publish
Push stacked atomic Pull/Merge Requests.
What is this?
git-publish is a Python script that manages your stacked commits into separate PR (GitHub) / MR (GitLab). It assigns a change ID to each commit in the commit message through a commit message hook. When calling git-publish directly, each commit will be pushed to a dedicated remote branch and PR / MR will be created targeting the right branch to retain the commit history. If commits are amended, git-publish will refer to the change ID to find the associated branch and keep everything in order.
Get started
Install git-publish for everyday use:
$ uv tool install git-publish
For local development of this repo:
$ uv build
$ uv tool install . -e
Set the required environment variables (add to your shell profile) or rely on the token resolver:
GITHUB_TOKEN— required for GitHub projects (repo scope sufficient for PRs). The tool will also acceptGH_TOKEN, or fall back togh auth tokenand Git credential helper.GITLAB_TOKEN— required for GitLab projects (api scope)GITLAB_URL— optional GitLab instance URL; default:https://gitlab.comGITPUBLISH_BRANCH_PREFIX— optional branch/id prefix; defaults to your OS usernameGITPUBLISH_CHANGE_ID_PREFIX— prefix used in commit messages for change ids; defaults toChange-Id:
You can also drop these in a local .env file at the repo root; it will be auto‑loaded when you run the tool:
# .env
GITHUB_TOKEN=ghp_...
GITLAB_TOKEN=glpat-...
GITLAB_URL=https://gitlab.example.com
GITPUBLISH_BRANCH_PREFIX=alice
GITPUBLISH_CHANGE_ID_PREFIX=Change-Id:
Run it in your repository:
$ git-publish
Tips:
- You can also run it as a Git subcommand:
git publish(Git will invokegit-publishon PATH). - Make sure you are on one of the main branches (
main,master,development,develop) and that it is up-to-date with its tracking branch. - After commit, check the commit message contains a line like
Change-Id: user/1a2b(or your chosen prefix).
Hooks
When you run the tool, it installs a commit-msg hook at .git/hooks/commit-msg that ensures a Change‑Id is present in every commit.
- Update: re-run
git-publishto validate the existing hook content. - Remove:
rm .git/hooks/commit-msg.
Safety
This tool will:
- Stash and later unstash your working tree when dirty
- Force‑push ephemeral branches (one per commit)
- Delete temporary local branches after publishing
Make sure your main branch is clean and tracking the correct remote.
Development tasks
Using the task runner:
$ uv run task lint # ruff (check) + pyright
$ uv run task format # ruff --fix
$ uv run task test # pytest
Troubleshooting
- "Branch is not up‑to‑date with its tracking branch" →
git fetchthengit pull --ff-only. - "Must be on a main branch" → switch to
main,master,development, ordevelop. - "Empty GITHUB_TOKEN/GITLAB_TOKEN" → export in your shell or add to
.env.
Dev containers and CI-friendly token resolution
git-publish now resolves the GitHub token in this order:
GITHUB_TOKEN(orGH_TOKEN) environment variablegh auth tokenif the GitHub CLI is installed and logged in- Git credential helper (
git credential fillforgithub.com)
This works well in VS Code tasks and dev containers where environment variables may not be present.
Dev container task example:
{
"version": "2.0.0",
"tasks": [
{
"label": "git-publish",
"type": "shell",
"command": "bash",
"args": [
"-lc",
"GITHUB_TOKEN=$(gh auth token 2>/dev/null || true) git publish"
],
"problemMatcher": []
}
]
}
Alternatively, add a .env file in the workspace (not committed) with GITHUB_TOKEN=... which the tool auto‑loads.
Example output
git-publish info: My feature commit
🔗 https://github.com/owner/repo/pull/123
Next
- Add nested blocking dependencies (available in GitLab 16.6+)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file git_publish-0.1.0.tar.gz.
File metadata
- Download URL: git_publish-0.1.0.tar.gz
- Upload date:
- Size: 49.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
90ebddd4e7741bf57ecf7b5cb6f5621d2c928be6cd9f45aee0c046fda985f780
|
|
| MD5 |
0b7c4cc2a426469e250da41cf1a6edbe
|
|
| BLAKE2b-256 |
aa61ddb5cb418518e4d353e7c6b630c64ebecbbac9beb9f87a863c709065989c
|
Provenance
The following attestation bundles were made for git_publish-0.1.0.tar.gz:
Publisher:
publish.yml on warrenseine/git-publish
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
git_publish-0.1.0.tar.gz -
Subject digest:
90ebddd4e7741bf57ecf7b5cb6f5621d2c928be6cd9f45aee0c046fda985f780 - Sigstore transparency entry: 566982497
- Sigstore integration time:
-
Permalink:
warrenseine/git-publish@397d02380c655a975ef9eccad63c6df541ccc094 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/warrenseine
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@397d02380c655a975ef9eccad63c6df541ccc094 -
Trigger Event:
release
-
Statement type:
File details
Details for the file git_publish-0.1.0-py3-none-any.whl.
File metadata
- Download URL: git_publish-0.1.0-py3-none-any.whl
- Upload date:
- Size: 10.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8141628b8d48853b3fee44fb7b4aafbedd66ded91b768e7d1d6b75a4c1f978bd
|
|
| MD5 |
918ead564688dae727ebd1a5c335342e
|
|
| BLAKE2b-256 |
89d8dfaafb001d266bc890d3f1d27a3e994bff4e1c93a689aeaacebed57f6769
|
Provenance
The following attestation bundles were made for git_publish-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on warrenseine/git-publish
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
git_publish-0.1.0-py3-none-any.whl -
Subject digest:
8141628b8d48853b3fee44fb7b4aafbedd66ded91b768e7d1d6b75a4c1f978bd - Sigstore transparency entry: 566982508
- Sigstore integration time:
-
Permalink:
warrenseine/git-publish@397d02380c655a975ef9eccad63c6df541ccc094 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/warrenseine
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@397d02380c655a975ef9eccad63c6df541ccc094 -
Trigger Event:
release
-
Statement type: