{"id":20976912,"url":"https://github.com/pixelbrackets/patchbot","last_synced_at":"2026-02-19T15:07:45.687Z","repository":{"id":145819785,"uuid":"285226783","full_name":"pixelbrackets/patchbot","owner":"pixelbrackets","description":"A tool to automate the distribution of patches to various Git repositories","archived":false,"fork":false,"pushed_at":"2026-02-15T20:55:50.000Z","size":218,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-02-16T02:59:21.215Z","etag":null,"topics":["bot","distribution","git","mandalascript","migration","patch","patchbot","php"],"latest_commit_sha":null,"homepage":"https://gitlab.com/pixelbrackets/patchbot/","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pixelbrackets.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","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}},"created_at":"2020-08-05T08:23:53.000Z","updated_at":"2026-02-15T20:55:53.000Z","dependencies_parsed_at":"2023-04-09T19:47:04.692Z","dependency_job_id":null,"html_url":"https://github.com/pixelbrackets/patchbot","commit_stats":null,"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"purl":"pkg:github/pixelbrackets/patchbot","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pixelbrackets%2Fpatchbot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pixelbrackets%2Fpatchbot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pixelbrackets%2Fpatchbot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pixelbrackets%2Fpatchbot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pixelbrackets","download_url":"https://codeload.github.com/pixelbrackets/patchbot/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pixelbrackets%2Fpatchbot/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29619297,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-19T13:04:20.082Z","status":"ssl_error","status_checked_at":"2026-02-19T13:03:33.775Z","response_time":117,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["bot","distribution","git","mandalascript","migration","patch","patchbot","php"],"created_at":"2024-11-19T04:56:18.702Z","updated_at":"2026-02-19T15:07:45.669Z","avatar_url":"https://github.com/pixelbrackets.png","language":"PHP","readme":"# Patchbot\n\n![Logo](docs/icon.png)\n\n[![Version](https://img.shields.io/packagist/v/pixelbrackets/patchbot.svg?style=flat-square)](https://packagist.org/packages/pixelbrackets/patchbot/)\n[![Build Status](https://img.shields.io/gitlab/pipeline/pixelbrackets/patchbot?style=flat-square)](https://gitlab.com/pixelbrackets/patchbot/pipelines)\n[![Made With](https://img.shields.io/badge/made_with-php-blue?style=flat-square)](https://gitlab.com/pixelbrackets/patchbot#requirements)\n[![License](https://img.shields.io/badge/license-gpl--2.0--or--later-blue.svg?style=flat-square)](https://spdx.org/licenses/GPL-2.0-or-later.html)\n[![Contribution](https://img.shields.io/badge/contributions_welcome-%F0%9F%94%B0-brightgreen.svg?labelColor=brightgreen\u0026style=flat-square)](https://gitlab.com/pixelbrackets/patchbot/-/blob/master/CONTRIBUTING.md)\n\nA tool to automate the distribution of patches to various Git repositories.\n\n![Screenshot](docs/screenshot.png)\n\n_⭐ You like this package? Please star it or send a tweet. ⭐_\n\n## Vision\n\nThis project provides a tool to distribute changes to a several Git repositories\nwith as little manual work as possible.\n\nThe need for this came up when I had to apply the same manual changes to many\nof my repositories:\n\n- Rename files having a certain name pattern, remove a line of code\n  only if a condition matches, replace a link in all documents, execute another\n  tool which then changes files and so on. Nothing a plain \n  [Git patch file](https://git-scm.com/docs/git-format-patch/2.7.6) could solve,\n  but something that could be automated nevertheless with a migration script.\n- Create a feature branch, commit all changes with a good commit message,\n  push the branch, wait for tests to turn green, open a pull request.\n- Repeat the same steps in many other repositories.\n\nThe idea is to do the changes only once and move the repetitions to a tool.\nSaving time, preventing careless mistakes and shun monotonous work.\n\n📝 Take a look at this\n[blog post with real world examples](https://pixelbrackets.de/notes/distribute-patches-to-many-git-repositories-with-patchbot)\nand how Patchbot helps to reduce technical debt across your own Git\nrepositories.\n\nSee [»Usage«](#usage) for example commands.\n\nThe package follows the KISS principle.\n\n## Requirements\n\n- PHP\n- Git\n\n## Installation\n\n💡 Use the \n[skeleton package](https://packagist.org/packages/pixelbrackets/patchbot-skeleton/)\nto create an example project right away.\n\n- `composer create-project pixelbrackets/patchbot-skeleton`\n\nPackagist Entry to install Patchbot only\nhttps://packagist.org/packages/pixelbrackets/patchbot/\n\n- `composer require pixelbrackets/patchbot`\n\n### Access rights\n\n🔑 *The user running Patchbot needs to have access to the target repository.*\n\nMake sure that the user running Patchbot is allowed to clone and push to\nall target repositories.\n\nPatchbot allows all protocols for connections to remotes which are supported\nby Git natively:\n[FILE, HTTP/HTTPS, SSH](https://git-scm.com/book/en/v2/Git-on-the-Server-The-Protocols)\n\nThe recommended protocol is SSH.\n\n#### HTTPS Credentials\n\nGit by default does not store any credentials. So *every connection* to a\nrepository by HTTPS will prompt for a username and password.\n\nTo avoid these password prompts when using HTTPS URIs with Patchbot\nyou have two options:\n\n- Allow Git to store credentials in memory for some time\n  - The password prompt then pops up once only for each host\n  - Example command to keep the credentials in memory for 15 minutes:\n    ```bash\n    git config --global credential.helper 'cache --timeout=900'\n    ```\n- Force Git to use SSH protocol checkouts instead of HTTP/HTTPS\n  - Has to be configured for each host\n  - Example commands to set up the replacements for GitHub, GitLab \u0026 BitBucket\n    ```bash\n    git config --global url.\"ssh://git@github.com/\".insteadOf \"https://github.com/\"\n    git config --global url.\"ssh://git@gitlab.com/\".insteadOf \"https://gitlab.com/\"\n    git config --global url.\"ssh://git@bitbucket.org/\".insteadOf \"https://bitbucket.org/\"\n    ```\n\n## Source\n\nhttps://gitlab.com/pixelbrackets/patchbot/\n\nMirror https://github.com/pixelbrackets/patchbot/\n\n## Usage\n\nPatchbot patches a given Git repository.\n\nThis means it will clone the repository, create a feature branch,\nrun a given PHP patch script, commit the changes with a given commit message\nand push the branch to the remote.\n\nPatchbot uses a lean file structure to organize patches (see\n[skeleton package](https://packagist.org/packages/pixelbrackets/patchbot-skeleton/)).\n\nThe directory `patches` contains a collection of all your “patch directories“.\n\nEach patch directory always contains at least a PHP script named `patch.php`\nand a commit message named `commit-message.txt`. \n\nExample file structure:\n```\n.\n|-- patches\n|   |-- template\n|   |   |-- commit-message.txt\n|   |   `-- patch.php\n|   `-- yet-another-patch\n|       |-- commit-message.txt\n|       `-- patch.php\n|-- vendor\n|   `-- bin\n|       `-- patchbot\n|-- composer.json\n`-- README.md\n```\n\nThis way a migration script may be created once and applied in a row to\nmany repositories or ad hoc every time the need arises.\n\n### Apply patch\n\nPass the name of the patch directory as `patch-name` and the Git repository as\n`repository-url` to the `patchbot` script.\n\nExample command applying the patch script in directory `template` to\nthe repository `https://git.example.com/repository`:\n```bash\n./vendor/bin/patchbot patch --patch-name=template --repository-url=https://git.example.com/repository\n```\n\nExample command applying the patch script in directory `template` to\nthe repository `ssh://git@git.example.com/repository.git`:\n```bash\n./vendor/bin/patchbot patch --patch-name=template --repository-url=ssh://git@git.example.com/repository.git\n```\n\n**Custom options**\n\nTo create the feature branch based on the branch `development`\ninstead of the default main branch use this command:\n```bash\n./vendor/bin/patchbot patch --source-branch=development --patch-name=template --repository-url=https://git.example.com/repository\n```\n\nPatchbot will use a random name for the feature branch. To use a custom name\nlike `feature-1337-add-license-file` for the feature branch instead run:\n```bash\n./vendor/bin/patchbot patch --branch-name=feature-1337-add-license-file --patch-name=template --repository-url=https://git.example.com/repository\n```\n\nIt is recommended to let a CI run all tests. That's why Patchbot creates a\nfeature branch by default. If you want to review complex changes manually before\nthe commit is created, then use the `halt-before-commit` option:\n\n```bash\n./vendor/bin/patchbot patch --halt-before-commit --patch-name=template --repository-url=https://git.example.com/repository\n```\n\nTo be more verbose add `-v` to each command. Add `-vvv` for debugging.\nThis will show all steps and commands applied by Patchbot.\nThe flag `--no-ansi` will remove output formation.\n\n### Merge feature branch\n\n✨️Patchbot intentionally creates a feature branch to apply patches.\n\nWhen you reviewed the feature branch and all CI tests are successful then\nyou can use Patchbot again to merge the feature branch.\n\nExample command to merge branch `bugfix-add-missing-lock-file` into\nbranch `main` in repository `https://git.example.com/repository`:\n```bash\n./vendor/bin/patchbot merge --source=bugfix-add-missing-lock-file --target=main --repository-url=https://git.example.com/repository\n```\n\n### Add a new patch\n\nExample command to create a directory named `add-changelog-file` and\nall files needed for the patch (the name is slugified automatically):\n```bash\n./vendor/bin/patchbot create --patch-name=\"Add CHANGELOG file\"\n```\nOr copy the example folder `template` manually instead and rename it as desired.\n\nNow replace the patch code in `patch.php` and the commit message\nin `commit-message.txt`.\n\n🛡 ️Patchbot runs the patch script isolated, as a consequence it is possible\nto run the script without Patchbot.\n\n💡 Tip: Switch to an existing projekt repository, run\n`php \u003cpath to patch directory\u003e/patch.php` and develop the patch incrementally.\nWhen development is finished, then commit it and use Patchbot to distribute\nthe patch to all other repositories.\n\nThe patch code will be executed in the root directory scope of the target\nrepository, keep this in mind for file searches.\n\n### Share a patch\n\nThe patches created in the patch directory are probably very specific to your\norganisation or domain. So the best way to share the patches in your\norganisation is to share the patch project as Git repository.\n\nHowever, since a motivation for this tool was to reuse migration scripts,\nyou could share general-purpose scripts with others though.\n\nOne possible way is to create a GitHub Gist for a single patch.\n\nExample command using the CLI gem [gist](https://github.com/defunkt/gist)\nto upload the `template` patch:\n```bash\ncd patches/template/\ngist -d \"Patchbot Patch »template« - Just a template without changes\" patch.php commit-message.txt\n```\n\n🔎 Search for [Gists with Patchbot tags](https://gist.github.com/search?l=PHP\u0026q=%23patchbot).\n\n### Import a shared patch\n\nCopy \u0026 paste all files manually to import an existing patch from another source.\n\nIf the source is a Git repository then a Git clone command is sufficient.\n\nExample command importing the\n[Gist `https://gist.github.com/pixelbrackets/98664b79c788766e4248f16e268c5745`](https://gist.github.com/pixelbrackets/98664b79c788766e4248f16e268c5745)\nas patch `add-editorconfig`:\n```bash\ngit clone --depth=1 https://gist.github.com/pixelbrackets/98664b79c788766e4248f16e268c5745 patches/add-editorconfig/\nrm -r patches/add-editorconfig/.git\n```\n\n### Batch processing\n\nTo apply a patch to 1 or 20 repositories you may run the Patchbot script\nrepeatedly with different URLs. To do this with 300 repos you may want\nto use the batch processing mode instead.\n\nThis mode will trigger the `patch` or `merge` command for a list of\nrepositories. The list is expected as CSV file named `repositories.csv`.\n\n*repositories.csv - Example file content, with repository \u0026 branch to use*\n```csv\nrepository-url,main-branch\nhttps://git.example.com/projecta,main\nhttps://git.example.com/projectb,main\nhttps://git.example.com/projectc,development\n```\n\nThe `patch` subcommand allows all options of the `patch` command, except for\n`repository-url` and `source-branch`. Both are provided by the\n`repositories.csv` file instead.\n\nThe following command will apply the patch script `update-changelog` to all\nrepository URLs in the first column of the `repositories.csv` file and create\nthe feature branch based on the name in the second column.\n\n```bash\n./vendor/bin/patchbot batch patch --patch-name=update-changelog\n```\n\nThe `merge` subcommand also allows all options of the `merge` command,\nexcept for `repository-url` and `target`. Both are provided by the\n`repositories.csv` file instead.\n\nThe next command will merge the feature branch `feature-add-phpcs-rules`\ninto the branch name in the second column of the `repositories.csv` file and\nin all repositories of the first column:\n```bash\n./vendor/bin/patchbot batch merge --source=feature-add-phpcs-rules\n```\n\n**Different branch names**\n\nWhen the branch names used in the `patch` and `merge` subcommand differ,\nor when you need to merge the feature branch into several stage branches\nyou may provide a file with all branches and pass the name of the designated\nbranch column as option `branch-column`.\n\n*repositories.csv - Example file content with many branch columns*\n```csv\nrepository-url,main,development,integration-stage,test-stage\nhttps://git.example.com/projecta,main,development,integration,testing\nhttps://git.example.com/projectb,main,dev,stage/integration,stage/test\nhttps://git.example.com/projectc,live,development,stage/integration,stage/test\n```\n\nApply the patch `rename-changelog` to the feature branch\n`feature-rename-changelog`, which is based on branch name given in column\n`development`:\n```bash\n./vendor/bin/patchbot batch patch --branch-column=development patch-name=rename-changelog branch-name=feature-rename-changelog\n```\nNow merge the feature branch into the branch name given in column `test-stage`\nand then into the of given in column `integration-stage`:\n```bash\n./vendor/bin/patchbot batch merge --branch-column=test-stage source=feature-rename-changelog\n./vendor/bin/patchbot batch merge --branch-column=integration-stage source=feature-rename-changelog\n```\n\n## License\n\nGNU General Public License version 2 or later\n\nThe GNU General Public License can be found at http://www.gnu.org/copyleft/gpl.html.\n\n## Author\n\nDan Untenzu (\u003cmail@pixelbrackets.de\u003e / [@pixelbrackets](https://pixelbrackets.de))\n\n\nSee [CHANGELOG.md](./CHANGELOG.md)\n\n## Contribution\n\nThis script is Open Source, so please use, share, patch, extend or fork it.\n\n[Contributions](./CONTRIBUTING.md) are welcome!\n\n## Feedback\n\nPlease send some [feedback](https://pixelbrackets.de/) and share how this\npackage has proven useful to you or how you may help to improve it.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpixelbrackets%2Fpatchbot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpixelbrackets%2Fpatchbot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpixelbrackets%2Fpatchbot/lists"}