{"id":31041959,"url":"https://github.com/acarapetis/jj-pre-push","last_synced_at":"2025-09-14T10:53:59.843Z","repository":{"id":306592634,"uuid":"1025501815","full_name":"acarapetis/jj-pre-push","owner":"acarapetis","description":"Run pre-commit.com before `jj git push`","archived":false,"fork":false,"pushed_at":"2025-08-05T23:56:52.000Z","size":31,"stargazers_count":15,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-06T09:53:27.285Z","etag":null,"topics":["git","jj","jujutsu","pre-commit","vcs"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/acarapetis.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-07-24T10:54:29.000Z","updated_at":"2025-09-04T13:53:12.000Z","dependencies_parsed_at":"2025-07-26T17:59:44.383Z","dependency_job_id":"3fcf9036-9dfc-49d2-9bda-3eeef29d2a6a","html_url":"https://github.com/acarapetis/jj-pre-push","commit_stats":null,"previous_names":["acarapetis/jj-pre-push"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/acarapetis/jj-pre-push","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/acarapetis%2Fjj-pre-push","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/acarapetis%2Fjj-pre-push/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/acarapetis%2Fjj-pre-push/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/acarapetis%2Fjj-pre-push/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/acarapetis","download_url":"https://codeload.github.com/acarapetis/jj-pre-push/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/acarapetis%2Fjj-pre-push/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275094380,"owners_count":25404446,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-14T02:00:10.474Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["git","jj","jujutsu","pre-commit","vcs"],"created_at":"2025-09-14T10:53:56.581Z","updated_at":"2025-09-14T10:53:59.831Z","avatar_url":"https://github.com/acarapetis.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# jj-pre-push\n\n[![PyPI](https://img.shields.io/pypi/v/jj-pre-push)](https://pypi.org/project/jj-pre-push/)\n\nA _very limited_ integration between [jj](https://jj-vcs.github.io) and\n[pre-commit](https://pre-commit.com/) allowing you to run your pre-push hooks in a\ncolocated jj/git repository.\n\nI don't expect this to last forever, it's just a stopgap until some jj-native mechanism\narrives that can take over.\n\nPrior art:\n\n- \u003chttps://www.aazuspan.dev/blog/automating-pre-push-checks-with-jujutsu/\u003e\n- Various comments on \u003chttps://github.com/jj-vcs/jj/issues/405\u003e\n\n## Usage\n\nUse `jj-pre-push push` (or an alias - personally I use `jj push`) as a replacement for\n`jj git push`. It takes all the same arguments, and does the following:\n\n1. Determines which bookmarks the corresponding `jj git push` will update on the remote,\n   and how they would change.\n2. For each of these bookmarks in turn:\n   - Checks out the bookmark to the working copy\n   - Runs the pre-push hooks defined in your .pre-commit-config.yaml on the same set of\n     files pre-commit would when pushing the same change. (For existing branches that's\n     the files touched in the range `old`...`new`; for new branches it's the files\n     touched in all ancestors of `new` that aren't present on the remote.)\n   - Reports any failures; and if any files were modified reports the change ID(s) in which\n     these modifications can be found.\n3. If all hooks succeeded on all branches, executes `jj git push` with the arguments\n   provided; otherwise nothing is pushed.\n4. Returns the working copy to its original change.\n\nIf there is no .pre-commit-config.yaml in your workspace root, `jj-pre-push push`\nimmediately delegates to `jj git push`.\n\nBy default `jj-pre-push` produces no console output of its own unless hooks fail. If\nyou'd like to see more details about what's happening, you can use `jj-pre-push\n--log-level=INFO push`.\n\n## Installation\n\nIf you have [uv](https://docs.astral.sh/uv/) installed and you're planning to use an\nalias anyway, you can avoid explicitly installing at all with `uvx`, e.g. with this jj\nconfiguration for `jj push`:\n\n```toml\n[aliases]\npush = [\"util\", \"exec\", \"--\", \"uvx\", \"jj-pre-push\", \"push\"]\n```\n\nOtherwise, install the PyPI package `jj-pre-push` in whichever way you prefer; e.g. `uv tool\ninstall jj-pre-push` or `pip install jj-pre-push`, and use `jj-pre-push push` as\ndescribed earlier.\n\n## Usage with jjui\n\nIf you're a [jjui](https://github.com/idursun/jjui) fan (I think maybe you should be!),\nhere's an example `jjui/config.toml` snippet showing how you can define custom commands\nto invoke jj-pre-push: one to perform the default `jj push`, and one to push the\nbookmarks attached to the change you have currently selected in the UI.\n\n```toml\n[custom_commands]\n\"jj push\" = { key = [\"p\"], args = [\"push\"] }\n\"jj push selected bookmark(s)\" = { key = [\"P\"], args = [\"push\", \"-r\", \"$change_id\"] }\n```\n\nNote that these depend upon the `jj push` alias defined in the previous section.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Facarapetis%2Fjj-pre-push","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Facarapetis%2Fjj-pre-push","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Facarapetis%2Fjj-pre-push/lists"}