Unfortunately OpenGL complicates things a little because the internalFormat you request is not necessarily what the driver itself will use.
The classic example of this is that a GL_RGB internalFormat is actually more likely to be a 4-component format with the fourth (alpha) set to 1 (assuming a 0…1 range). So if you set GL_RGB for both internalFormat and format, you’re still probably going to get a conversion.
You should note that on many platforms the fast path is actually to use GL_BGRA for format, and that GL_BGRA does not exist as a valid value for internalFormat, so even the component ordering of internalFormat shouldn’t be seen as significant.
You should also note that on older OpenGL when you request an internalFormat of GL_RGB or GL_RGBA, OpenGL is not actually obliged to give you 8-bits per channel (or whatever else you may assume it is); so if it gives you something else and if you supply data that assumes otherwise, you’re definitely going to get a conversion.
In more recent versions of OpenGL things are a little bit better because there is a set list of internalFormats that drivers must support, and this list is of explicitly sized formats, but there is still confusion over the whole GL_RGB thing. This is completely in accord with the OpenGL philosophy, where drivers or hardware that may actually have native support for 3-component internalFormats are also supported, so it’s helpful for the developer who wants something that will work and support what they asked for, but not too helpful for the developer who wants to explicitly specify a fast mode without the driver getting in the way.
Things are also a little clearer with GL_ARB_texture_storage where the format and type parameters don’t exist when initially specifying a texture. This can aid understanding, because it helps to demonstrate that format and type don’t actually relate to how OpenGL itself stores the texture.