Yes, you're correct; changes in the org are overwritten when deploying, and local changes are overwritten when retrieving. The "workaround" is that each developer should be developing in their own Sandbox, and using a code repository, such as git or subversion. It has never been a good idea for multiple developers to work in the same org.
There is a reason why even Professional Edition gets 10 sandboxes, and higher editions get at least 100 sandboxes. One Hundred. Think about that. Do you have a hundred developers in your org? Is it really worth sharing orgs when you can easily create as many as you need? Also, if you're using Dev Hub, you can create at least 10 scratch orgs every single day. If you're using DX mode, this means you can literally create a new org every week if you want/need to.
Also, if that's still too much trouble, there are alternative solutions. DX is only one such tool. For example, we use GearSet at our place (note: this is not an endorsement, simply personal experience), which we use to migrate changes between any Git branch to any other, or any org to any other, or any combination (org to git, git to org). There are different tools out there that can help.
However, at the end of the day, no matter which tool you work with, developers should not be sharing the same org for development. It's very hard and troublesome to get it right, accidents happen all the time. For that reason, it's also equally important to use a code repository so that any accidents can be undone by simply checking out an older version of a file.
DX isn't a superpower tool that's above all the rest, but it is a practical tool when used as part of a design protocol that is recommended by salesforce.com. Use repositories, and do not share orgs. Use scratch orgs or Sandboxes, one per developer, refreshed as frequently as you need, even daily.