{"id":13616846,"url":"https://github.com/balbuf/composer-git-merge-driver","last_synced_at":"2025-04-05T20:05:47.473Z","repository":{"id":46697319,"uuid":"122296027","full_name":"balbuf/composer-git-merge-driver","owner":"balbuf","description":"Custom git merge driver to minimize merge conflicts in composer.json and composer.lock files","archived":false,"fork":false,"pushed_at":"2023-03-12T16:57:20.000Z","size":24,"stargazers_count":129,"open_issues_count":9,"forks_count":7,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-03-29T19:02:09.406Z","etag":null,"topics":["composer","composer-json","composer-lock","git","git-merge","git-merger","merge","merge-conflict","merge-conflicts"],"latest_commit_sha":null,"homepage":null,"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/balbuf.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}},"created_at":"2018-02-21T05:22:01.000Z","updated_at":"2025-03-07T13:29:26.000Z","dependencies_parsed_at":"2024-06-19T05:42:27.728Z","dependency_job_id":null,"html_url":"https://github.com/balbuf/composer-git-merge-driver","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/balbuf%2Fcomposer-git-merge-driver","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/balbuf%2Fcomposer-git-merge-driver/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/balbuf%2Fcomposer-git-merge-driver/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/balbuf%2Fcomposer-git-merge-driver/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/balbuf","download_url":"https://codeload.github.com/balbuf/composer-git-merge-driver/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247393568,"owners_count":20931812,"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","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":["composer","composer-json","composer-lock","git","git-merge","git-merger","merge","merge-conflict","merge-conflicts"],"created_at":"2024-08-01T20:01:34.024Z","updated_at":"2025-04-05T20:05:47.453Z","avatar_url":"https://github.com/balbuf.png","language":"PHP","funding_links":[],"categories":["PHP","Per-File Merge Drivers"],"sub_categories":[],"readme":"# Composer JSON Git Merge Driver\n\nThe Composer JSON Git Merge Driver provides a mechanism to more effectively merge\n`composer.json` and `composer.lock` files that have been modified simultaneously\nin separate branches / development histories. The [custom git merge driver][merge driver]\nis invoked when the composer JSON files require a merge more complex than a\nsimple \"fast forward.\"\n\n## How it Works\n\nThe merge driver replaces git's standard merge algorithm only for composer's JSON files:\ninstead of analyzing the files for changed lines, the JSON is parsed and the actual properties\nand values are compared for changes. As such, the merge driver is able to more gracefully\nhandle most new, updated, and removed dependencies in your composer files. A merge conflict\nis only triggered when the version constraint, locked version number, or presence / absence\nof the same dependency has been modified in multiple development histories involved in the\nmerge.\n\nFor instance, if a certain dependency is updated in one branch and removed in another,\na merge conflict is triggered because it is unclear which change for that dependency is\ndesired following the merge. However, if a new, different dependency is appended to the\n`require` section in both branches, the merge driver will understand that both should\nbe kept, whereas the standard git merge driver would trigger a merge conflict because\nthe same line has been edited in both branches.\n\nMore generally, all object data structures are merged gracefully and recursively, meaning\nother composer configuration properties in the composer JSON files (e.g. `extra` and\n`config`) will be merged properly as well\u0026mdash;whenever changes are not ambiguous. In fact,\nthe merge driver will work on any JSON file whose outermost data structure is an object.\n\n### Composer Lock Handling\n\nFor the the lock file in particular, special handling is performed to minimize the potential\nfor merge conflicts. For example, the locked dependency data is converted into an object\nfor the purposes of merging and converted back to the proper data structure when the merge\nis complete. As well, the `content-hash` property is excluded from the merge, as the very\nnature of this property guarantees that two differing branches would have conflicting values.\nThe content hash is used by composer to efficiently recognize that the `composer.json` file\nhas changed, so the actual value is not necessarily important after a merge has occured.\nAs a workaround for not being able to generate an accurate hash, the merge driver sets its\nown unique value for the hash to signal to composer that a change has occurred; the value is\na simple message instructing you to run `composer update --lock` so composer can regenerate\nthe real hash!\n\n[merge driver]: https://git-scm.com/docs/gitattributes#_defining_a_custom_merge_driver\n\n## Installation\n\nThe merge driver can be installed globally or per repo and configured and activated globally or per repo,\ni.e. you can install the driver globally but only activate it on certain projects.\n\n### 1. Install the merge driver on your system.\n\nUse composer to install the driver globally:\n\n```sh\n$ composer global require balbuf/composer-git-merge-driver\n```\n\nor just in a particular repo:\n\n```sh\n$ composer require --dev balbuf/composer-git-merge-driver\n```\n\nNote that if you are installing the driver via the latter (per repo) method, this will be added\nto the repo's `composer.json` and thus will be installed as a dependency for all users of the repo.\n\n### 2. Configure the merge driver with git.\n\nThe driver is made available for use by informing git of its existence via a [git config][git config] file:\n\n```\n[merge \"composer_json\"]\n    name = composer JSON file merge driver\n    driver = composer-git-merge-driver %O %A %B %L %P\n    recursive = binary\n```\n\nTo open the git config file for editing in your default command line text editor:\n\n```sh\n$ git config -e\n```\n\nBy default, this allows you to edit the config file for the current repo, meaning the driver\nis only installed locally to the repo. To edit the global config file for your user, append the\n`--global` flag; to edit the system-wide config file, append the `--system` flag.\n\nCopy and paste the block above into the config file and save it. This example assumes that your `$PATH`\nincludes [Composer's vendor bin][vendor bin] path (by default, `~/.composer/vendor/bin` for global\ninstallation or `./vendor/bin` for repo installation). If not, be sure to update your `$PATH` or\nadd the appropriate path to the binary on the `driver` line.\n\nA sample `.gitconfig` file is included in this repo for convenience. If `composer-git-merge-driver` is \ninstalled as a project dependency, the sample `.gitconfig` file can be installed like so:\n```\n$ git config --add include.path $(git rev-parse --show-toplevel)/vendor/balbuf/composer-git-merge-driver/.gitconfig\n```\n\nFor more information about git config files, refer to the [git documentation][git config].\n\n[git config]: https://git-scm.com/docs/git-config\n[vendor bin]: https://getcomposer.org/doc/articles/vendor-binaries.md#can-vendor-binaries-be-installed-somewhere-other-than-vendor-bin-\n\n### 3. Activate the merge driver.\n\nFinally, the merge driver must be activated for `composer.json` and `composer.lock` files via\na [git attributes][git attributes] file:\n\n```\ncomposer.json merge=composer_json\ncomposer.lock merge=composer_json\n```\n\nTo activate only for a specific repo, edit the `.git/info/attributes` file inside of the repo.\nTo activate globally for your user, edit the `~/.gitattributes` file; to activate system-wide,\nedit the `$(prefix)/etc/gitattributes` file (e.g. `/usr/local/etc/gitattributes`). Copy and\npaste the block above into the config file and save it. In some cases the file may not yet exist,\nin which case you can simply create the file at the aforementioned path.\n\nFor more information about git attributes files, refer to the [git documentation][git attributes].\n\n[git attributes]: https://git-scm.com/docs/gitattributes\n\n## Usage\n\nThe merge driver is automatically invoked any time a `composer.json` and/or `composer.lock` file\nmust be merged in a repo where the driver is activated. If there are any merge conflicts within\nthe files, the standard git merge conflict procedure kicks in: you will be alerted of which file(s)\ncontain conflicts, and conflicts are denoted via the standard conflict markers (e.g. `\u003c\u003c\u003c\u003c\u003c\u003c\u003c`).\n\nIf there are no conflicts and the merge can be applied cleanly, the merge completes as normal.\nHowever, a changed lock file results in a non-standard `content-hash` value (whether there are\nconflicts or not). While there should be no harm in leaving the hash value as-is, it's best to\nlet composer regenerate the hash. To do so, simply run:\n\n```sh\n$ composer update --lock\n```\n\nThe value of the hash actually informs you to take this action, but if the merge completes with\nno conflicts, you may not even notice the message. When there are conflicts, this step should\nbe completed after fixing the conflicts but before finishing the merge. If there were no conflicts\nand the merge completed, you can avoid creating an additional commit by amending the merge commit:\n\n```sh\n$ composer update --lock\n$ git add composer.lock\n$ git commit --amend --no-edit\n```\n\n## Additional Information\n\n### Requirements\n\nThe merge driver is written in PHP and requires at least version 5.4.\n\n### Known Limitations\n\n- The merge driver parses and regenerates the JSON to complete the merge. As such, some formatting\nmay be lost or altered in the process. For the `composer.json` file, the driver attempts to detect\nthe indentation preference of the file in the working tree and replicate that indentation when\nthe JSON is regenerated, which should minimize formatting changes. However, some whitespace style\ncannot be preserved, e.g. fewer line breaks or more whitespace. While the interpreted contents\nof the file will not be compromised, the formatting could result in extraneous changes to the file\nas a result of the merge. (In keeping with the behavior of composer, the `composer.lock` file is\nregenerated by the default behavior of PHP's `json_encode` function and is consistently indented.)\n\n- When a merge conflict occurs where the last property of an object is removed, accepting the removed\nversion will result in invalid syntax due to a trailing comma on the preceding property. Care should\nbe taken to verify the syntax of the overall file and manually update accordingly.\n\n### Acknowledgements\n\nThanks to [@christian-blades-cb](https://gist.github.com/christian-blades-cb/f75ec813f15393498b6c)\nand [@jphass](https://gist.github.com/jphaas/ad7823b3469aac112a52) for the inspiration and examples.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbalbuf%2Fcomposer-git-merge-driver","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbalbuf%2Fcomposer-git-merge-driver","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbalbuf%2Fcomposer-git-merge-driver/lists"}