{"id":14235864,"url":"https://github.com/mbucc/shmig","last_synced_at":"2026-01-14T20:24:43.489Z","repository":{"id":10953233,"uuid":"13263886","full_name":"mbucc/shmig","owner":"mbucc","description":"Database migration tool written in BASH.","archived":false,"fork":false,"pushed_at":"2024-10-19T00:48:38.000Z","size":131,"stargazers_count":469,"open_issues_count":13,"forks_count":50,"subscribers_count":11,"default_branch":"master","last_synced_at":"2026-01-14T02:53:33.536Z","etag":null,"topics":["database-migrations","devops","mysql","postgresql","shell","sql","sqlite3"],"latest_commit_sha":null,"homepage":null,"language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mbucc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2013-10-02T06:06:06.000Z","updated_at":"2025-10-31T19:45:19.000Z","dependencies_parsed_at":"2024-12-13T01:30:59.179Z","dependency_job_id":"a1764609-0acf-4efb-a2e9-eac8e282a47f","html_url":"https://github.com/mbucc/shmig","commit_stats":null,"previous_names":["naquad/shmig"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/mbucc/shmig","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mbucc%2Fshmig","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mbucc%2Fshmig/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mbucc%2Fshmig/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mbucc%2Fshmig/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mbucc","download_url":"https://codeload.github.com/mbucc/shmig/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mbucc%2Fshmig/sbom","scorecard":{"id":631463,"data":{"date":"2025-08-11","repo":{"name":"github.com/mbucc/shmig","commit":"b2dee60321456901827d5aa3440d854e475bfb81"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":2,"reason":"Found 6/25 approved changesets -- score normalized to 2","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: BSD 3-Clause \"New\" or \"Revised\" License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: containerImage not pinned by hash: Dockerfile:1: pin your Docker image by updating alpine:latest to alpine:latest@sha256:4bcff63911fcb4448bd4fdacec207030997caf25e9bea4045fa6c8c44de311d1","Info:   0 out of   1 containerImage dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 11 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-21T08:00:13.156Z","repository_id":10953233,"created_at":"2025-08-21T08:00:13.156Z","updated_at":"2025-08-21T08:00:13.156Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28434434,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T18:57:19.464Z","status":"ssl_error","status_checked_at":"2026-01-14T18:52:48.501Z","response_time":107,"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":["database-migrations","devops","mysql","postgresql","shell","sql","sqlite3"],"created_at":"2024-08-20T21:02:26.221Z","updated_at":"2026-01-14T20:24:43.467Z","avatar_url":"https://github.com/mbucc.png","language":"Shell","readme":"SHMIG [![Build Status](https://travis-ci.org/mbucc/shmig.svg?branch=master)](https://travis-ci.org/mbucc/shmig)\n=====\n\nA database migration tool written in BASH consisting of just one\nfile - [`shmig`](https://github.com/naquad/shmig/blob/master/shmig).\n\nAutomated Tests\n-----\n\n| Shell | DB  | Result |\n| ----- | --- | ------ |\n| /bin/bash | sqlite3 | ![](https://raw.githubusercontent.com/mbucc/shmig_test/master/badges/alpine-3.8-bash-sqlite3.png) |\n| /bin/bash | mysql:5.7 | ![](https://raw.githubusercontent.com/mbucc/shmig_test/master/badges/alpine-3.8-bash-mysql-5.7.png) |\n| /bin/bash | postgres:9.6 | ![](https://raw.githubusercontent.com/mbucc/shmig_test/master/badges/alpine-3.8-bash-postgres-9.6.png) |\n\nSee https://github.com/mbucc/shmig_test.\n\n\n\nQuick Start\n----------\n```\n  $ cd shmig\n  $ make install\n  $ cd $HOME\n  $ mkdir migrations\n  $ shmig -t sqlite3 -d test.db create mytable\n  generated ./migrations/1470490964-mytable.sql\n  $ cat ./migrations/1470490964-mytable.sql\n  -- Migration: mytable\n  -- Created at: 2016-08-06 09:42:44\n  -- ====  UP  ====\n\n  PRAGMA foreign_keys = ON;\n\n  BEGIN;\n\n  COMMIT;\n\n  -- ==== DOWN ====\n\n  PRAGMA foreign_keys = ON;\n\n  BEGIN;\n\n  COMMIT;\n  $ # In normal usage, you would add SQL to this migration file.\n  $ shmig -t sqlite3 -d test.db migrate\n  shmig: creating migrations table: shmig_version\n  shmig: applying  'mytable'    (1470490964)... done\n  $ ls -l test.db\n  -rw-r--r--  1 mark  staff  12288 Aug  6 09:41 test.db\n  $ shmig -t sqlite3 -d test.db rollback\n  shmig: reverting 'mytable'    (1470490964)... done\n  $ shmig -h | wc -l\n  73\n  $\n```\n\nEdit the function `sqlite3_up_text()` and `sqlite3_down_text()` in\nshmig if you don't like the default SQL template.\n\n\nWhy?\n----\n\nCurrently there are lots of database migration tools such as\n[DBV](http://dbv.vizuina.com/), [Liquibase](http://www.liquibase.org/),\n[sqitch](http://sqitch.org/), [Flyway](http://flywaydb.org/)\nand other framework-specific ones (for Ruby on Rails, Yii, Laravel,\n...). But they all are pretty heavy, with lots of dependencies (or\neven unusable outside of their stack), some own DSLs...\n\nI needed some simple, reliable solution with minimum dependencies\nand able to run in pretty much any POSIX-compatible environment\nagainst different databases (PostgreSQL, MySQL, SQLite3).\n\nAnd here's the result.\n\nIdea\n----\n\nRDMS'es are bundled along with their console clients. MySQL has\n`mysql`, PostgreSQL has `psql` and SQLite3 has `sqlite3`. And that's\nit! This is enough for interacting with database in batch mode w/o\nany drivers or connectors.\n\nUsing client options one can make its output suitable for batch\nprocessing with standard UNIX text-processing tools (`sed`, `grep`,\n`awk`, ...). This is enough for implementing simple migration system\nthat will store current schema version information withing database\n(see\n[`SCHEMA_TABLE`](https://github.com/naquad/shmig/blob/a814690d5040e6aa8f05f112a8b66db9eedb1d07/shmig.conf.example#L21-L22)\nvariable in\n[`shmig.conf.example`](https://github.com/naquad/shmig/blob/master/shmig.conf.example)).\n\nUsage\n-----\n\nSHMIG tries to read configuration from the configuration file\n`shmig.conf` in the current working directory.  A sample configuration\nfile is\n[`shmig.conf.example`](https://github.com/naquad/shmig/blob/master/shmig.conf.example).\n\nYou can also provide an optional config override file by creating\nthe file `shmig.local.conf`.  This allows you to provide a default\nconfiguration which is version-controlled with your project, then\nspecify a non-version-controlled local config file that you can use\nto provide instance-specific config. (An alternative is to use\nenvrionment variables, though some people prefer concrete files to\nnebulous environment variables.) This works even with custom config\nfiles specified with the `-c` option.\n\nYou can also configure SHMIG from command line, or by using\nenvironmental variables.  The command line settings have higher\npriority than configuration files or environment settings.\n\nRequired options are:\n\n  1. `TYPE` or `-t` - database type\n  2. `DATABASE` or `-d` - database to operate on\n  3. `MIGRATIONS` or `-m` - directory with migrations\n\nAll other options (see `shmig.conf.example` and `shmig -h`) are not necessary.\n\nTo simplify usage, create `shmig.conf` in your project root directory\nwith your configuration directives.  When you `shmig \u003caction\u003e ...` \nin that directory, shmig will use the configuration in that file.\n\nFor detailed information see `shmig.conf.example` and `shmig -h`.\n\nMigrations\n----------\n\nMigrations are SQL files whose name starts with \"`\u003cUNIX TIMESTAMP\u003e-`\"\nand end with \".sql\".  The order that new migrations are applied is\n[determined](https://github.com/naquad/shmig/blob/master/shmig#L481)\nby the seconds-since-epoch time stamp in the filename, with the\noldest migration going first.\n\nEach migration contains two special markers: `-- ====  UP ====`\nthat marks start of section that will be executed when migration\nis applied and `-- ==== DOWN ====` that marks start of section that\nwill be executed when migration is reverted.\n\nFor example:\n\n```\n-- Migration: create users table\n-- Created at: 2013-10-02 07:03:11\n-- ====  UP  ====\nCREATE TABLE `users`(\n  id int not null primary key auto_increment,\n  name varchar(32) not null,\n  email varchar(255) not null\n);\n\nCREATE UNIQUE INDEX `users_email_uq` ON `users`(`email`);\n-- ==== DOWN ====\nDROP TABLE `users`;\n```\n\nEverything between `-- ==== UP ====` till `-- ==== DOWN ====` will \nbe executed when migration is applied and everything between \n`-- ==== DOWN ====` till the end of file will be executed when\nmigration is reverted. If migration is missing marker or contents\nof marker is empty then appropriate action will fail (i.e. if you're\ntrying to revert migration that has no or empty `-- ==== DOWN ====`\nmarker you'll get an error and script won't execute any migrations\nfollowing script with error). Also note those semicolons terminating\nstatements. They're required because you're basically typing that\ninto your database CLI client.\n\nSHMIG can generate skeleton migration for you, see `create` action.\n\nMigrations with test data\n----------\nOne nice feature of Liquibase is contexts, which are used to\nimplement different behavior based on environment; for example,\nin a development environment you can insert test data.\n\n`shmig` can support this with symbolic links.  For example, say\nyour production migrations are in `prod` and test data in `test`:\n\n```\n.\n└── migrations\n    ├── prod\n    │   └── 1485643154-create_table.sql\n    └── test\n        └── 1485648520-testdata.sql\n```\n\nTo create a test environment context, link the prod SQL in test directory:\n\n```\n$ cd migrations/test/\n$ ln -s ../prod/1485643154-create_table.sql\n```\n\n\n```\n.\n└── migrations\n    ├── prod\n    │   └── 1485643154-create_table.sql\n    └── test\n        ├── 1485643154-create_table.sql -\u003e ../prod/1485643154-create_table.sql\n        └── 1485648520-testdata.sql\n```\n\nWhen applying migrations to test, point shmig to the test directory either\nvia the command line or using the local config override file.\n\nSince migrations are applied in order of epoch seconds in the file name,\nthis works.\n\n\nCurrent state\n-------------\n\nStable and maintained.  Pull requests welcome.\n\n\nSecurity considerations\n-----------------------\n\nPassword is passed to `mysql` and `psql` via environment variable.\nThis can be a security issue if your system allows other users to\nread environment of process that belongs to another user. In most\nLinux distributions with modern kernels this is forbidden. You can\ncheck this (on systems supporting /proc file system) like this:\n`cat /proc/1/env` - if you get permission denied error then you're\nsecure.\n\nEfficiency\n----------\n\nBecause SHMIG is just a shell script it's not a speed champion.\nEvery time a statement is executed new client process is spawned.\nI didn't experience much issues with speed, but if you'll have then\nplease file an issue and maybe I'll get to that in detail.\n\nUsage with Docker\n-----------------\nShmig can be used and configured with env vars\n```\ndocker run -e PASSWORD=root -e HOST=mariadb -v $(pwd)/migrations:/sql --link mariadb:mariadb mkbucc/shmig:latest -t mysql -d db-name up\n```\n\nThis will attempt 3 retries of the command before exiting. This can \nbe useful in a docker-compose set up where the SHMIG container `depends_on`\nanother DB service within the docker-compose configuration.\n \n\nOS Packaging\n------------\n\nA [Debian](https://www.debian.org) package is available for shmig\nat https://packages.kaelshipman.me.\n\n[NixOS](https://nixos.org/) supports `shmig` on Linux and Darwin at the moment, the package can be\ninstalled into the user's profile by running `nix-env -iA nixos.shmig` since\n[18.03](https://nixos.org/nixos/manual/release-notes.html#sec-release-18.03).\n\n*Contributions for other systems would be greatly welcomed, and can be submitted via PR to this repo.\n\nTodo\n----\n\n  1. Speed. Some optimizations are definitely possible to speed things up.\n  2. A way to spawn just one CLI client. Maybe something with FIFOs and SIGCHLD handler.\n  3. Better documentation :\\\n\n","funding_links":[],"categories":["Shell"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmbucc%2Fshmig","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmbucc%2Fshmig","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmbucc%2Fshmig/lists"}