diff --git a/alembic/command.py b/alembic/command.py index 4897c0d9..798dbb71 100644 --- a/alembic/command.py +++ b/alembic/command.py @@ -385,6 +385,7 @@ def merge( message: Optional[str] = None, branch_label: Optional[_RevIdType] = None, rev_id: Optional[str] = None, + splice: bool = False, ) -> Optional[Script]: """Merge two revisions together. Creates a new migration file. @@ -435,6 +436,7 @@ def nothing(rev, context): refresh=True, head=revisions, branch_labels=branch_label, + splice=splice, **template_args, # type:ignore[arg-type] ) diff --git a/alembic/config.py b/alembic/config.py index 121a4459..dd2baa62 100644 --- a/alembic/config.py +++ b/alembic/config.py @@ -737,7 +737,7 @@ def __init__(self, prog: Optional[str] = None) -> None: "--splice", dict( action="store_true", - help="Allow a non-head revision as the 'head' to splice onto", + help="Allow using a non-head revision as a base by disabling head-only validation", ), ), "depends_on": ( diff --git a/tests/test_command.py b/tests/test_command.py index 8608ba18..54f7df26 100644 --- a/tests/test_command.py +++ b/tests/test_command.py @@ -44,6 +44,7 @@ from alembic.testing.fixtures import capture_engine_context_buffer from alembic.testing.fixtures import TestBase from alembic.util import compat +from alembic.util import CommandError from alembic.util.sqla_compat import _connectable_has_table @@ -276,6 +277,36 @@ def test_merge_cmd_revision_environment(self, rev_env): assert os.path.exists(rev.path) + def test_merge_cmd_with_splice(self): + cfg = self.cfg + self.a, self.b, self.c = three_rev_fixture(cfg) + self.d, self.e, self.f = multi_heads_fixture( + cfg, self.a, self.b, self.c + ) + assert_raises( + CommandError, + command.merge, + cfg, + [self.a, self.b], + rev_id="merge_no_splice", + splice=False, + ) + command.merge( + cfg, + [self.a, self.b], + rev_id="merge_with_splice", + splice=True, + ) + script = ScriptDirectory.from_config(cfg).get_revision("merge_with_splice") + assert script is not None + assert os.path.exists(script.path) + + with open(script.path, "r", encoding="utf-8") as fp: + contents = fp.read() + + assert self.a in contents + assert self.b in contents + class CurrentTest(_BufMixin, TestBase): @classmethod