diff --git a/gdb/cli/cli-decode.c b/gdb/cli/cli-decode.c
index 7c98029f9f4..132b0ca659a 100644
--- a/gdb/cli/cli-decode.c
+++ b/gdb/cli/cli-decode.c
@@ -179,18 +179,26 @@ cmd_list_element::command_components () const
 
 static struct cmd_list_element *
 do_add_cmd (const char *name, enum command_class theclass,
+	    cmd_simple_func_ftype *fun,
 	    const char *doc, struct cmd_list_element **list)
 {
   struct cmd_list_element *c = new struct cmd_list_element (name, theclass,
 							    doc);
 
+  set_cmd_simple_func (c, fun);
+
   /* Turn each alias of the old command into an alias of the new
      command.  */
   c->aliases = delete_cmd (name, list, &c->hook_pre, &c->hookee_pre,
 			   &c->hook_post, &c->hookee_post);
-
   for (cmd_list_element &alias : c->aliases)
-    alias.alias_target = c;
+    {
+      alias.func = c->func;
+      alias.function = c->function;
+      alias.subcommands = c->subcommands;
+      alias.allow_unknown = c->allow_unknown;
+      alias.alias_target = c;
+    }
 
   if (c->hook_pre)
     c->hook_pre->hookee_pre = c;
@@ -233,9 +241,7 @@ struct cmd_list_element *
 add_cmd (const char *name, enum command_class theclass,
 	 const char *doc, struct cmd_list_element **list)
 {
-  cmd_list_element *result = do_add_cmd (name, theclass, doc, list);
-  result->func = NULL;
-  result->function.simple_func = NULL;
+  cmd_list_element *result = do_add_cmd (name, theclass, NULL, doc, list);
   return result;
 }
 
@@ -244,8 +250,7 @@ add_cmd (const char *name, enum command_class theclass,
 	 cmd_simple_func_ftype *fun,
 	 const char *doc, struct cmd_list_element **list)
 {
-  cmd_list_element *result = do_add_cmd (name, theclass, doc, list);
-  set_cmd_simple_func (result, fun);
+  cmd_list_element *result = do_add_cmd (name, theclass, fun, doc, list);
   return result;
 }
 
diff --git a/gdb/python/py-cmd.c b/gdb/python/py-cmd.c
index 5cc392af175..d66311d623b 100644
--- a/gdb/python/py-cmd.c
+++ b/gdb/python/py-cmd.c
@@ -524,8 +524,15 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw)
          name_allocated, so release it.  */
       cmd_name.release ();
 
-      /* There appears to be no API to set this.  */
+      /* There appears to be no API to set the below members.
+	 In particular, we cannot pass cdmpy_function to add_prefix_cmd and
+	 add_cmd above.  This means that if cmd has aliases, its aliases have
+	 been re-targeted to this freshly built CMD with a null func and
+	 function.simple_func (see cli-decode.c do_add_cmd).  So, we need to set
+	 the 'func' of the aliases of CMD.  */
       cmd->func = cmdpy_function;
+      for (cmd_list_element &alias : cmd->aliases)
+	alias.func = cmd->func;
       cmd->destroyer = cmdpy_destroyer;
       cmd->doc_allocated = 1;
       cmd->name_allocated = 1;
diff --git a/gdb/testsuite/gdb.python/py-cmd-alias.py b/gdb/testsuite/gdb.python/py-cmd-alias.py
new file mode 100644
index 00000000000..d62628841f4
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-cmd-alias.py
@@ -0,0 +1,28 @@
+class some_prefix_cmd (gdb.Command):
+  def __init__ (self):
+    super (some_prefix_cmd, self).__init__ ("some_prefix_cmd", gdb.COMMAND_OBSCURE, gdb.COMPLETE_NONE, True)
+  def invoke (self, arg, from_tty):
+    print ("some_prefix_cmd output, arg = %s" % arg)
+
+some_prefix_cmd ()
+
+def def_alias(alias : str, command_name : str) -> None:
+    """Defines an alias -a ALIAS = COMMAND_NAME.
+Traps the error if ALIAS is already defined (so as to be able to source
+this file again)."""
+    d = "alias " + alias + ' = ' + command_name
+    try:
+        gdb.execute (d)
+    except Exception as inst:
+        print(str(inst))
+
+
+def_alias("alias_of_some_prefix_cmd", "some_prefix_cmd")
+def_alias("other_alias_of_some_prefix_cmd", "some_prefix_cmd")
+
+class some_subcmd (gdb.Command):
+  def __init__ (self):
+    super (some_subcmd, self).__init__ ("some_prefix_cmd some_subcmd", gdb.COMMAND_OBSCURE)
+  def invoke (self, arg, from_tty):
+    print ("some_subcmd output, arg = %s" % arg)
+some_subcmd ()
diff --git a/gdb/testsuite/gdb.python/py-cmd.exp b/gdb/testsuite/gdb.python/py-cmd.exp
index 48c3e18f1cc..c7398889fd4 100644
--- a/gdb/testsuite/gdb.python/py-cmd.exp
+++ b/gdb/testsuite/gdb.python/py-cmd.exp
@@ -111,6 +111,23 @@ gdb_test_multiline "input new subcommand" \
 
 gdb_test "info newsubcmd ugh" "newsubcmd output, arg = ugh" "call newsubcmd"
 
+# Test sourcing twice a file that redefines a prefix command with aliases.
+set pyfile [gdb_remote_download host ${srcdir}/${subdir}/py-cmd-alias.py]
+foreach initial_load {1 0} {
+    if $initial_load {
+	gdb_test_no_output "source ${pyfile}" "load python file"
+    } else {
+	gdb_test "source ${pyfile}" \
+	    "Alias already exists: alias_of_some_prefix_cmd\r\nAlias already exists: other_alias_of_some_prefix_cmd" \
+	    "load again python file"
+    }
+    foreach cmd {"some_prefix_cmd" "alias_of_some_prefix_cmd" "other_alias_of_some_prefix_cmd"} {
+	gdb_test "$cmd ugh $initial_load" \
+	    "some_prefix_cmd output, arg = ugh $initial_load" \
+	    "call $cmd $initial_load"
+    }
+}
+
 # Test a command that throws gdb.GdbError.
 
 gdb_test_multiline "input command to throw error" \
