diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java
index 0213fbc029..209f35eeb3 100644
--- a/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java
@@ -901,7 +901,11 @@ public class RubyMessage extends RubyObject {
       if (fdef.isRepeated()) {
         copy.fields.put(fdef, this.getRepeatedField(context, fdef).deepCopy(context));
       } else if (fields.containsKey(fdef)) {
-        copy.setFieldInternal(context, fdef, fields.get(fdef));
+        if (fdef.getType() == FieldDescriptor.Type.MESSAGE) {
+          copy.setFieldInternal(context, fdef, ((RubyMessage) fields.get(fdef)).deepCopy(context));
+        } else {
+          copy.setFieldInternal(context, fdef, fields.get(fdef));
+        }
       } else if (builder.hasField(fdef)) {
         copy.fields.put(fdef, wrapField(context, fdef, builder.getField(fdef)));
       }
diff --git a/ruby/tests/common_tests.rb b/ruby/tests/common_tests.rb
index 09ea4d8c83..28494f9c08 100644
--- a/ruby/tests/common_tests.rb
+++ b/ruby/tests/common_tests.rb
@@ -701,6 +701,15 @@ module CommonTests
     assert m.repeated_msg[0].object_id != m2.repeated_msg[0].object_id
   end
 
+  def test_sub_message_deep_copy # regression test for issue 12505
+    m = proto_module::Foo.new(bar: proto_module::Bar.new(msg: "Hello World"))
+    m2 = Google::Protobuf.deep_copy(m)
+    assert_equal(m, m2)
+    assert_not_equal(m.object_id, m2.object_id)
+    assert_equal(m.bar, m2.bar)
+    assert_not_equal(m.bar.object_id, m2.bar.object_id)
+  end
+
   def test_message_eq
     m = proto_module::TestMessage.new(:optional_int32 => 42,
                                       :repeated_int32 => [1, 2, 3])