A while back I wrote a post about content types becoming unghosted when you edit them in the UI and there not being any way of reversing this without directly modifying the content database. That would put you in an unsupported state, so obviously it's not an option for most people. But as it turns out there is a supported way of doing this after all, it's just not very well documented...
A colleague of mine was having this same problem and informed me that he was able to fix it with the STSADM Deactivatefeature operation by adding the -force parameter.
Let us see what the Holy Gospel according to TechNet has to say about the -force parameter:
"force - Forces the feature to be uninstalled."
In other words, not much help to be found in the scriptures. But it works! When the feature containing the unghosted content type(s) is deactivated with the -force parameter the Definition column in the ContentTypes table goes back to NULL, meaning it is now using the XML definition again.
You can then use the gl-propagatecontenttype custom STSADM command from Gary Lapointe with the -updatefields parameter to push changes in the site content type down to the list content type.