diff --git a/commitizen/commands/changelog.py b/commitizen/commands/changelog.py
index aab613fffc..d934ac2940 100644
--- a/commitizen/commands/changelog.py
+++ b/commitizen/commands/changelog.py
@@ -144,9 +144,7 @@ def __call__(self):
                 tag_format=self.tag_format,
             )
 
-        commits = git.get_commits(
-            start=start_rev, end=end_rev, args="--author-date-order"
-        )
+        commits = git.get_commits(start=start_rev, end=end_rev, args="--topo-order")
         if not commits:
             raise NoCommitsFoundError("No commits found")
 
diff --git a/tests/commands/test_changelog_command.py b/tests/commands/test_changelog_command.py
index b98ec6e503..7805c99ad5 100644
--- a/tests/commands/test_changelog_command.py
+++ b/tests/commands/test_changelog_command.py
@@ -13,7 +13,14 @@
     NotAGitProjectError,
     NotAllowed,
 )
-from tests.utils import create_file_and_commit, wait_for_tag
+from tests.utils import (
+    create_branch,
+    create_file_and_commit,
+    get_current_branch,
+    merge_branch,
+    switch_branch,
+    wait_for_tag,
+)
 
 
 @pytest.mark.usefixtures("tmp_commitizen_project")
@@ -268,6 +275,75 @@ def test_changelog_hook_customize(mocker: MockFixture, config_customize):
     changelog_hook_mock.assert_called_with(full_changelog, full_changelog)
 
 
+@pytest.mark.usefixtures("tmp_commitizen_project")
+def test_changelog_with_non_linear_merges_commit_order(
+    mocker: MockFixture, config_customize
+):
+    """Test that commits merged non-linearly are correctly ordered in the changelog
+
+    A typical scenario is having two branches from main like so:
+    * feat: I will be merged first - (2023-03-01 11:35:51 +0100) |  (branchB)
+    | * feat: I will be merged second - (2023-03-01 11:35:22 +0100) |  (branchA)
+    |/
+    * feat: initial commit - (2023-03-01 11:34:54 +0100) |  (HEAD -> main)
+
+    And merging them, for example in the reverse order they were created on would give the following:
+    *   Merge branch 'branchA' - (2023-03-01 11:42:59 +0100) |  (HEAD -> main)
+    |\
+    | * feat: I will be merged second - (2023-03-01 11:35:22 +0100) |  (branchA)
+    * | feat: I will be merged first - (2023-03-01 11:35:51 +0100) |  (branchB)
+    |/
+    * feat: initial commit - (2023-03-01 11:34:54 +0100) |
+
+    In this case we want the changelog to reflect the topological order of commits,
+    i.e. the order in which they were merged into the main branch
+
+    So the above example should result in the following:
+    ## Unreleased
+
+    ### Feat
+    - I will be merged second
+    - I will be merged first
+    - initial commit
+    """
+    changelog_hook_mock = mocker.Mock()
+    changelog_hook_mock.return_value = "cool changelog hook"
+
+    create_file_and_commit("feat: initial commit")
+
+    main_branch = get_current_branch()
+
+    create_branch("branchA")
+    create_branch("branchB")
+
+    switch_branch("branchA")
+    create_file_and_commit("feat: I will be merged second")
+
+    switch_branch("branchB")
+    create_file_and_commit("feat: I will be merged first")
+
+    # Note we merge branches opposite order than author_date
+    switch_branch(main_branch)
+    merge_branch("branchB")
+    merge_branch("branchA")
+
+    changelog = Changelog(
+        config_customize,
+        {"unreleased_version": None, "incremental": True, "dry_run": False},
+    )
+    mocker.patch.object(changelog.cz, "changelog_hook", changelog_hook_mock)
+    changelog()
+    full_changelog = "\
+## Unreleased\n\n\
+\
+### Feat\n\n\
+- I will be merged second\n\
+- I will be merged first\n\
+- initial commit\n"
+
+    changelog_hook_mock.assert_called_with(full_changelog, full_changelog)
+
+
 @pytest.mark.usefixtures("tmp_commitizen_project")
 def test_changelog_multiple_incremental_do_not_add_new_lines(
     mocker: MockFixture, capsys, changelog_path, file_regression
diff --git a/tests/utils.py b/tests/utils.py
index a1e14ad88c..2efe13fa9e 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -26,6 +26,31 @@ def create_file_and_commit(message: str, filename: Optional[str] = None):
         raise exceptions.CommitError(c.err)
 
 
+def create_branch(name: str):
+    c = cmd.run(f"git branch {name}")
+    if c.return_code != 0:
+        raise exceptions.GitCommandError(c.err)
+
+
+def switch_branch(branch: str):
+    c = cmd.run(f"git switch {branch}")
+    if c.return_code != 0:
+        raise exceptions.GitCommandError(c.err)
+
+
+def merge_branch(branch: str):
+    c = cmd.run(f"git merge {branch}")
+    if c.return_code != 0:
+        raise exceptions.GitCommandError(c.err)
+
+
+def get_current_branch() -> str:
+    c = cmd.run("git rev-parse --abbrev-ref HEAD")
+    if c.return_code != 0:
+        raise exceptions.GitCommandError(c.err)
+    return c.out
+
+
 def create_tag(tag: str):
     c = git.tag(tag)
     if c.return_code != 0: