All of them.*
* Possibly excepting Profiles.
I'm making an assumption here: you don't want to use source control just for the fun of it, but you want to get some benefit from doing so beyond just throwing a copy of your source code into a backup directory every week. To do that, your source control needs to be an operational part of your org architecture and deployment strategy. You don't have to get 100% of the way to CI/CD (although I consider that a goal everyone should strive for!) but you should strive to put your VCS at the center of a well-considered architecture and make it the source of truth in your process.
If you source-control only your code, you get all the cost of maintaining a source control-based infrastructure, but lose out on the majority of the benefits. Your VCS will be acting as no more than an irregular backup system. You'll still have to manually migrate all of the other components upon which your code relies - schema, declarative automation, validation rules, and so forth - from org to org. That's a nasty and error-prone process.
Instead, I strongly recommend building out a complete VCS and deployment solution that encompasses as much of your application as you can manage. Include every metadata component you can deploy (coming back to Profiles in a bit). That likely won't be enough to get you to a 100% automated environment setup - some of a Salesforce's org's configuration is still not representable in code, so there'll be manual steps when you set up a new org - but it puts you in a very strong position to minimize and gradually automate those manual steps.
I'd envision two key goals of this project:
- Establish a pathway to production that is built around your VCS as the source of truth and origin of each deployment operation. This ensures you have a clear audit trail for all of your application changes, gives you the ability to roll back (insofar as that's possible on the Salesforce platform) deleterious changes, and helps you adopt governance and lifecycle best practices.
- Reduce the time required to build and configure a new Salesforce org with your application (for demos, testing, user acceptance testing, etc.) to the absolutely minimum possible by encapsulating everything you've built in VCS and making it easy to deploy and configure in a new org.
Profiles are the most challenging component to work with in source control. It is possible. I've done it. And doing it does give you more benefit, in that you can that much more easily spin up new orgs, and that much more easily migrate complete changes, including permissioning, from org to org.
But managing Profiles in source control is a real pain. They're tricky to retrieve completely because retrieving a Profile only returns the permissions for components that are also retrieved. They're tricky to migrate between heterogeneous environments because they retain references to features of the org shape and the entire schema in their source orgs (unless carefully edited).
So this is the one place where I generally say "If you don't want to source control Profiles, and you know your deployment architecture will work without them, so be it."
Use Permission Sets wherever you can!