From ad270da5941bddb2a71580f4d90ff40d0b7af956 Mon Sep 17 00:00:00 2001 From: Aravinth BALAKRISHNAN Date: Wed, 17 Dec 2025 21:05:23 +0100 Subject: [PATCH 1/2] Add reversed option when listing history of revisions --- alembic/command.py | 3 ++- alembic/config.py | 8 ++++++++ alembic/script/base.py | 8 ++++++-- alembic/script/revision.py | 8 +++++++- 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/alembic/command.py b/alembic/command.py index 4897c0d9..39f45a70 100644 --- a/alembic/command.py +++ b/alembic/command.py @@ -561,6 +561,7 @@ def history( rev_range: Optional[str] = None, verbose: bool = False, indicate_current: bool = False, + reversed: bool = False, ) -> None: """List changeset scripts in chronological order. @@ -592,7 +593,7 @@ def history( def _display_history(config, script, base, head, currents=()): for sc in script.walk_revisions( - base=base or "base", head=head or "heads" + base=base or "base", head=head or "heads", reversed=reversed ): if indicate_current: sc._db_current_indicator = sc.revision in currents diff --git a/alembic/config.py b/alembic/config.py index 121a4459..06dd3d30 100644 --- a/alembic/config.py +++ b/alembic/config.py @@ -756,6 +756,14 @@ def __init__(self, prog: Optional[str] = None) -> None: "generating one", ), ), + "reversed": ( + "-R", + "--reversed", + dict( + action="store_true", + help="Show the history in the reversed order", + ), + ), "version_path": ( "--version-path", dict( diff --git a/alembic/script/base.py b/alembic/script/base.py index f8417085..6e8a86b5 100644 --- a/alembic/script/base.py +++ b/alembic/script/base.py @@ -247,7 +247,7 @@ def _catch_revision_errors( raise util.CommandError(err.args[0]) from err def walk_revisions( - self, base: str = "base", head: str = "heads" + self, base: str = "base", head: str = "heads", reversed: bool = False ) -> Iterator[Script]: """Iterate through all revisions. @@ -261,7 +261,11 @@ def walk_revisions( """ with self._catch_revision_errors(start=base, end=head): for rev in self.revision_map.iterate_revisions( - head, base, inclusive=True, assert_relative_length=False + head, + base, + inclusive=True, + assert_relative_length=False, + reversed=reversed, ): yield cast(Script, rev) diff --git a/alembic/script/revision.py b/alembic/script/revision.py index 5825da34..0e76f4c2 100644 --- a/alembic/script/revision.py +++ b/alembic/script/revision.py @@ -793,6 +793,7 @@ def iterate_revisions( inclusive: bool = False, assert_relative_length: bool = True, select_for_downgrade: bool = False, + reversed: bool = False, ) -> Iterator[Revision]: """Iterate through script revisions, starting at the given upper revision identifier and ending at the lower. @@ -819,7 +820,12 @@ def iterate_revisions( assert_relative_length=assert_relative_length, ) - for node in self._topological_sort(revisions, heads): + topological_sort = ( + self._topological_sort(revisions, heads)[::-1] + if reversed + else self._topological_sort(revisions, heads) + ) + for node in topological_sort: yield not_none(self.get_revision(node)) def _get_descendant_nodes( From 2eab5259df2f685021197beb83df3f766670ae16 Mon Sep 17 00:00:00 2001 From: Aravinth BALAKRISHNAN Date: Thu, 15 Jan 2026 10:47:10 +0100 Subject: [PATCH 2/2] Add test for the reversed flag --- tests/test_command.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/test_command.py b/tests/test_command.py index 8608ba18..5f2ebffb 100644 --- a/tests/test_command.py +++ b/tests/test_command.py @@ -209,6 +209,16 @@ def test_history_indicate_current(self): buf, [self.c, self.b, self.a], currents=(self.b,), env_token=True ) + def test_history_full_reversed(self): + self.cfg.stdout = buf = self._buf_fixture() + command.history(self.cfg, verbose=True, reversed=True) + self._eq_cmd_output(buf, [self.a, self.b, self.c]) + + def test_history_num_range_reversed(self): + self.cfg.stdout = buf = self._buf_fixture() + command.history(self.cfg, "%s:%s" % (self.a, self.b), verbose=True, reversed=True) + self._eq_cmd_output(buf, [self.a, self.b]) + class RevisionEnvironmentTest(_BufMixin, TestBase): def setUp(self):