{"id":49311225,"url":"https://github.com/tmaier/rails-schema-merge-driver","last_synced_at":"2026-05-02T19:01:38.410Z","repository":{"id":353924923,"uuid":"1221438351","full_name":"tmaier/rails-schema-merge-driver","owner":"tmaier","description":"Git merge driver that auto-resolves Rails schema version conflicts in db/schema.rb.","archived":false,"fork":false,"pushed_at":"2026-04-26T11:21:18.000Z","size":49,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-29T16:34:31.502Z","etag":null,"topics":["git","git-merge-driver","gitattributes","merge-driver","rails","rails-schema","ruby","rubygem"],"latest_commit_sha":null,"homepage":"https://rubygems.org/gems/rails-schema-merge-driver","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tmaier.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-26T07:51:18.000Z","updated_at":"2026-04-26T11:21:22.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/tmaier/rails-schema-merge-driver","commit_stats":null,"previous_names":["tmaier/rails-schema-merge-driver"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/tmaier/rails-schema-merge-driver","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tmaier%2Frails-schema-merge-driver","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tmaier%2Frails-schema-merge-driver/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tmaier%2Frails-schema-merge-driver/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tmaier%2Frails-schema-merge-driver/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tmaier","download_url":"https://codeload.github.com/tmaier/rails-schema-merge-driver/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tmaier%2Frails-schema-merge-driver/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32470879,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-30T13:12:12.517Z","status":"ssl_error","status_checked_at":"2026-04-30T13:12:06.837Z","response_time":57,"last_error":"SSL_read: 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":["git","git-merge-driver","gitattributes","merge-driver","rails","rails-schema","ruby","rubygem"],"created_at":"2026-04-26T13:00:55.052Z","updated_at":"2026-04-30T17:00:41.398Z","avatar_url":"https://github.com/tmaier.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# rails-schema-merge-driver\n\n[![Gem Version](https://img.shields.io/gem/v/rails-schema-merge-driver.svg)](https://rubygems.org/gems/rails-schema-merge-driver)\n[![CI](https://github.com/tmaier/rails-schema-merge-driver/actions/workflows/main.yml/badge.svg)](https://github.com/tmaier/rails-schema-merge-driver/actions/workflows/main.yml)\n[![Ruby Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://github.com/standardrb/standard)\n\nA git custom merge driver that auto-resolves the most common conflict in Rails\nschema files — the bumped `define(version: N)` line — by keeping the higher\nversion. Real content conflicts are left for a human.\n\n## Why\n\n`db/schema.rb` is regenerated on every migration, so the `version:` argument at\nthe top of the file changes on every concurrent branch. Whenever two branches\nadd migrations and meet at a merge, git flags this line as a conflict — but it\nisn't a real conflict: the right answer is always _the higher version_, which\nalready implies the union of both migrations.\n\nThis driver delegates to git's built-in three-way merge, then post-processes\nthe resulting conflict region: if the only diverging line is `define(version:\nN)`, it picks the higher version and writes the file. Anything else is left as\na normal conflict with markers in place, exiting non-zero so git knows the file\nstill needs human attention.\n\n## Supported formats\n\n- `ActiveRecord::Schema[X.Y].define(version: N)` — standard Rails `db/schema.rb`.\n- `DataMigrate::Data.define(version: N)` — `db/data_schema.rb` from the\n  [`data_migrate`](https://github.com/ilyakatz/data-migrate) gem.\n\nTolerates `merge.conflictstyle = diff3` and `zdiff3` (three-section markers).\n\n## Installation\n\nAdd to your Gemfile in the development group:\n\n```ruby\ngem \"rails-schema-merge-driver\", group: :development, require: false\n```\n\n`require: false` is important: the gem ships only an executable, so nothing\nneeds to autoload at app boot. Without it, `Bundler.require` would either fail\nlooking for a hyphenated path or load `lib/rails_schema_merge_driver.rb`\nunnecessarily.\n\nThen `bundle install`. The `git-merge-rails-schema` executable becomes\navailable under `bundle exec`. For a system install instead:\n\n```sh\ngem install rails-schema-merge-driver\n```\n\n## Setup (per repository)\n\nThe driver needs to be wired in two places: `.gitattributes` (which files it\napplies to) and `.git/config` (the driver definition itself, which is _not_\nversioned and must be set up by every contributor).\n\n### 1. `.gitattributes`\n\n```gitattributes\ndb/schema.rb       merge=rails-schema\ndb/data_schema.rb  merge=rails-schema   # only if you use the data_migrate gem\n```\n\nThe second line is only needed for projects that depend on the\n[`data_migrate`](https://github.com/ilyakatz/data-migrate) gem.\n\n### 2. `.git/config`\n\nEach contributor's clone needs the driver registered. Either run these once:\n\n```sh\ngit config --local merge.rails-schema.name 'keep newer Rails schema version'\ngit config --local merge.rails-schema.driver 'git-merge-rails-schema %O %A %B %L'\n```\n\n…or — recommended — wire it into your `bin/setup` so every contributor's clone\nis configured automatically when they bootstrap the project. Example, adapted\nfrom the [Librario](https://www.librario.de) `bin/setup` (the project this gem\nwas extracted from):\n\n```ruby\ndef configure_git_merge_drivers\n  system \"git config --local merge.rails-schema.name 'keep newer Rails schema version'\"\n  system \"git config --local merge.rails-schema.driver 'git-merge-rails-schema %O %A %B %L'\"\nend\n\nconfigure_git_merge_drivers\n```\n\n`git config --local` is idempotent, so this is safe to re-run.\n\nIf you installed the gem via bundler with `require: false`, you may need to\nprefix the driver command with `bundle exec` so the executable is found from\ninside the project's gem environment:\n\n```sh\ngit config --local merge.rails-schema.driver 'bundle exec git-merge-rails-schema %O %A %B %L'\n```\n\n## How it works\n\n1. The driver shells out to `git merge-file --marker-size=N current base\n   other`, which performs the standard three-way text merge.\n2. It reads the result and looks for a conflict region whose only diverging\n   line is a `.define(version: N)` call (handling diff3/zdiff3 base sections).\n3. If found, it replaces the region with whichever side has the higher numeric\n   version (underscores stripped) and writes the file back.\n4. Exits 0 if the file is fully resolved (no remaining `\u003c\u003c\u003c\u003c\u003c\u003c\u003c` markers),\n   exits 1 otherwise so git surfaces the remaining conflict to the user.\n\n`git merge-file` exit codes are passed through carefully: a hard failure (nil\nor negative status) aborts immediately, since silently treating it as\n\"resolved\" would drop the other side's changes.\n\n## Development\n\n```sh\nbin/setup            # bundle install\nbundle exec rake     # default: test + standard\nbundle exec rake test\nbundle exec rake standard\n```\n\nTo experiment in an IRB session:\n\n```sh\nbin/console\n```\n\nTo install this gem onto your local machine, run `bundle exec rake install`.\n\n## Releasing\n\nReleases are published to RubyGems.org via [trusted publishing][tp] (OIDC, no\nAPI keys) by `.github/workflows/release.yml`, triggered when a `v*` tag is\npushed. Steps:\n\n1. Bump `RailsSchemaMergeDriver::VERSION` in\n   `lib/rails_schema_merge_driver/version.rb`, then run `bundle exec rake test` so `Gemfile.lock` (which path-references the gem itself) picks up\n   the new version.\n2. Move the relevant entries from `[Unreleased]` to a new dated section in\n   `CHANGELOG.md`, following the [Keep a Changelog][kac] format.\n3. Commit `version.rb`, `Gemfile.lock`, and `CHANGELOG.md`; push to `main`;\n   wait for CI to pass.\n4. Tag and push:\n   ```sh\n   git tag v0.x.0\n   git push origin v0.x.0\n   ```\n\nThe workflow then:\n\n- Authenticates to RubyGems.org via OIDC (no secrets required).\n- Runs `bundle exec rake release` — which builds the gem and pushes it\n  (skips re-tagging because the tag already exists, per `bundler/gem_helper.rb`).\n- Creates a GitHub Release at the tag with the CHANGELOG section as notes and\n  the `.gem` file attached as a downloadable asset.\n\n[tp]: https://guides.rubygems.org/trusted-publishing/\n[kac]: https://keepachangelog.com/en/1.1.0/\n\n## Acknowledgements\n\n- Originally extracted from the [Librario](https://www.librario.de)\n  application (a Rails-based library management system) where this driver was\n  developed and battle-tested.\n- Adapted from [tpope's gist](https://gist.github.com/tpope/643979), which\n  proposed the original `railsschema` merge-driver idea.\n- See [git's gitattributes(5) docs](https://git-scm.com/docs/gitattributes#_defining_a_custom_merge_driver)\n  for the full custom merge-driver protocol.\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at\n\u003chttps://github.com/tmaier/rails-schema-merge-driver\u003e.\n\n## License\n\nThe gem is available as open source under the terms of the\n[MIT License](https://opensource.org/licenses/MIT).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftmaier%2Frails-schema-merge-driver","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftmaier%2Frails-schema-merge-driver","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftmaier%2Frails-schema-merge-driver/lists"}