diff --git a/mpcdf_common.py b/mpcdf_common.py
index 70e5ada57d18232ba366b857abf66b92d14d5ca4..dd83c2861609fe5772bc032fc464257ab527b2c9 100644
--- a/mpcdf_common.py
+++ b/mpcdf_common.py
@@ -618,7 +618,7 @@ def parse_prjconf(api_url, project):
 
 
 def mpcdf_setup_subproject(api_url, project, distribution, microarchitecture,
-                           parent=None, dry_run=False, remove_old=False, all_possible=False, only_project=False):
+                           parent=None, dry_run=False, diff=False, remove_old=False, all_possible=False, only_project=False):
 
     if parent and not dry_run:
         for attribute in config_attributes + default_attributes:
@@ -843,7 +843,17 @@ Macros:
         build.tail = "\n  "
         root.insert(list(root).index(root.find("./repository")), build)
 
-    root.getchildren()[-1].tail = "\n"
+    def sort_repos(root):
+        # Sort existing repositories to be able to compare
+        repos = root.findall("./repository")
+        for repo in repos:
+            root.remove(repo)
+        repos = sorted(repos, key=lambda child: child.get("name"))
+        for repo in repos:
+            root.append(repo)
+        root.getchildren()[-1].tail = "\n"
+
+    sort_repos(root)
     new_prj = ElementTree.tostring(root, encoding=osc.core.ET_ENCODING)
 
     for name in sorted(prjconf_repos.keys()):
@@ -862,9 +872,36 @@ Macros:
 
     new_prjconf = "".join(prjconf_head) + "\n".join(prjconf_ours) + "".join(prjconf_tail)
 
+    if diff:
+        def stringdiff(s1, label1, s2, label2):
+            import os
+            from subprocess import call
+            from tempfile import NamedTemporaryFile
+
+            old = NamedTemporaryFile("w+", delete=False)
+            new = NamedTemporaryFile("w+", delete=False)
+
+            old.write(s1)
+            old.close()
+            new.write(s2)
+            new.close()
+
+            call(["diff", "-s", "-u", old.name, "--label", "old-prjconf", new.name, "--label", "new-prjconf"])
+            os.unlink(old.name)
+            os.unlink(new.name)
+
+        stringdiff("".join(orig_prjconf), "old-prjconf", new_prjconf, "new-prjconf")
+
+        old_prj_root = project_meta(api_url, project)
+        sort_repos(old_prj_root)
+        old_prj = ElementTree.tostring(old_prj_root, encoding=osc.core.ET_ENCODING)
+
+        stringdiff(old_prj + "\n", "old-prj-meta", new_prj + "\n", "new-prj-meta")
+
     if dry_run:
-        print("osc meta prjconf {0} -F - <<EOF\n{1}\nEOF\n".format(project, new_prjconf))
-        print("osc meta prj {0} -F - <<EOF\n{1}\nEOF\n".format(project, new_prj))
+        if not diff:
+            print("osc meta prjconf {0} -F - <<EOF\n{1}\nEOF\n".format(project, new_prjconf))
+            print("osc meta prj {0} -F - <<EOF\n{1}\nEOF\n".format(project, new_prj))
     else:
         if new_prjconf == "".join(orig_prjconf):
             print("prjconf unchanged")
diff --git a/mpcdf_setup_subproject.py b/mpcdf_setup_subproject.py
index eb19a1d1838bf0f96f30a9f35db9443633687723..56965b7288edcf51c90b1f946dac013deb30a5fa 100644
--- a/mpcdf_setup_subproject.py
+++ b/mpcdf_setup_subproject.py
@@ -11,6 +11,8 @@ import osc.cmdln
 
 @osc.cmdln.option('-n', '--dry-run', action="store_true",
                   help="Do not actually run anything but output the resulting XML configuration")
+@osc.cmdln.option('--diff', action="store_true",
+                  help="Show (only) differences of prjconf and project meta")
 @osc.cmdln.option('--only-project', action="store_true",
                   help="Only change project metadata, do not iterate over packages and change their enabled repositories")
 @osc.cmdln.option('--remove-old', action="store_true", default=False,
@@ -51,4 +53,4 @@ def do_mpcdf_setup_subproject(self, subcmd, opts, *args):
 
     mpcdf_setup_subproject(self.get_api_url(),
                            project, distribution, microarchitecture,
-                           dry_run=opts.dry_run, remove_old=opts.remove_old, only_project=opts.only_project)
+                           dry_run=opts.dry_run, diff=opts.diff, remove_old=opts.remove_old, only_project=opts.only_project)