diff --git a/dim b/dim
index f1ca50f0d81100bb69047e1fc42c0eb94a1d22d8..c62531a4c8b758790fc5a8566831eac1a849c510 100755
--- a/dim
+++ b/dim
@@ -333,6 +333,28 @@ if message_id is not None:
 EOF
 }
 
+message_print_body ()
+{
+	python2 <<EOF
+import email
+
+def print_part(part):
+    mtype = part.get_content_maintype()
+    if mtype == 'text':
+        print(part.get_payload(decode=True))
+
+def print_msg(file):
+    msg = email.message_from_file(file)
+    if msg.is_multipart():
+        for part in msg.get_payload():
+            print_part(part)
+    else:
+        print_part(msg)
+
+print_msg(open('$1', 'r'))
+EOF
+}
+
 # append all arguments as tags at the end of the commit message of HEAD
 function dim_commit_add_tag
 {
@@ -1048,6 +1070,48 @@ function rangeish()
 	fi
 }
 
+function dim_extract_tags
+{
+	local branch range file tags
+
+	branch=$1
+	shift
+	range=$(rangeish "$1")
+	file=$(mktemp)
+
+	assert_branch $branch
+	assert_repo_clean
+
+	cat > $file
+
+	tags=$(message_print_body "$file" | grep -ai '^[^>]*[A-Za-z-]\+: [^ ]')
+
+	rm -f $file
+
+	if [[ -z "$tags" ]]; then
+		return 0
+	fi
+
+	tags=$(printf -- "# *** extracted tags ***\n%s" "$tags")
+
+	git filter-branch -f --msg-filter "cat ; echo \"$tags\"" $range
+}
+
+function dim_extract_queued
+{
+	dim_extract_tags drm-intel-next-queued "$@"
+}
+
+function dim_extract_fixes
+{
+	dim_extract_tags drm-intel-fixes "$@"
+}
+
+function dim_extract_next_fixes
+{
+	dim_extract_tags drm-intel-next-fixes "$@"
+}
+
 dim_alias_check_patch=checkpatch
 dim_alias_cp=checkpatch
 function dim_checkpatch