diff --git a/tools/pickman/control.py b/tools/pickman/control.py
index 39ce57d0895..3e69cba7a9a 100644
--- a/tools/pickman/control.py
+++ b/tools/pickman/control.py
@@ -1473,40 +1473,57 @@ def push_mr(args, branch_name, title, description):
     return bool(mr_url)
 
 
-def prepare_apply(dbs, source, branch):
-    """Prepare for applying commits from a source branch
+def _prepare_get_commits(dbs, source):
+    """Get the next commits to apply, handling skips.
 
-    Gets the next commits, sets up the branch name, and prints info about
-    what will be applied.
+    Fetches the next batch of commits from the source.
 
     Args:
         dbs (Database): Database instance
         source (str): Source branch name
-        branch (str): Branch name to use, or None to auto-generate
 
     Returns:
-        tuple: (ApplyInfo, return_code) where ApplyInfo is set if there are
-            commits to apply, or None with return_code indicating the result
-            (0 for no commits, 1 for error)
+        tuple: (NextCommitsInfo, return_code) where return_code is None
+            on success, or an int (0 or 1) if there is nothing to do
     """
     info, err = get_next_commits(dbs, source)
-
     if err:
         tout.error(err)
         return None, 1
 
     if not info.commits:
-        # If advance_to is set, advance source past fully-processed merges
         if info.advance_to:
             dbs.source_set(source, info.advance_to)
             dbs.commit()
             tout.info(f"Advanced source '{source}' to "
                       f'{info.advance_to[:12]}')
-            # Retry with updated position
-            return prepare_apply(dbs, source, branch)
-        tout.info('No new commits to cherry-pick')
+        else:
+            tout.info('No new commits to cherry-pick')
         return None, 0
 
+    return info, None
+
+
+def prepare_apply(dbs, source, branch):
+    """Prepare for applying commits from a source branch
+
+    Gets the next commits, sets up the branch name, and prints info about
+    what will be applied.
+
+    Args:
+        dbs (Database): Database instance
+        source (str): Source branch name
+        branch (str): Branch name to use, or None to auto-generate
+
+    Returns:
+        tuple: (ApplyInfo, return_code) where ApplyInfo is set if there are
+            commits to apply, or None with return_code indicating the result
+            (0 for no commits, 1 for error)
+    """
+    info, ret = _prepare_get_commits(dbs, source)
+    if ret is not None:
+        return None, ret
+
     commits = info.commits
 
     # Save current branch to return to later
