Connecting 3v digital output to Arduino using bi-directional level shifting (mosfet)
The bidirectional MOSFET level shifter automatically detects when one side is pulled down, and then pulls the other side down. So it will still work if only one side is ever pulled down.

The pull-up resistors are needed to get a defined high level when no device is pulling the line down. When you have a push/pull output, you do not need the resistor on that side.

A pull-up resistor combines with any parasitic capacitances in the circuit to form an RC low-pass filter, i.e., the rising edge of the output signal is slowed down. This is typically not yet a problem at the 100 kHz of I²C, but might become one at higher frequencies.

The MC74VHC1GT125, or actual level shifters like the SN74LVC1T45, have push/pull outputs, so they can reach higher frequencies.

An optocoupler is used if you need galvanic isolation. When you connect the grounds of the two devices together, it is not needed (but would still work).