The hardest part of deployment.
THE PROBLEM
Code can be replaced wholesale. A database cannot, because it contains data you must keep.
MIGRATIONS
The standard answer. Each schema change is a numbered script, applied in order, recorded so it runs once.
Laravel, Rails and most frameworks provide this. WordPress does not, which is why WordPress deployments are usually code-only.
RULES THAT SAVE TROUBLE
Never edit a migration that has run on production. Write a new one. Make migrations reversible where you can. Add columns before you use them, and remove them in a later release, so old and new code both work during deployment. Test migrations on a copy of production data, not on an empty database.
CONTENT VERSUS SCHEMA
Schema changes deploy forward. Content is data and generally flows the other way, from production to staging, so testing is realistic.
Never deploy a staging database over production. It destroys everything written since the copy.
FOR WORDPRESS
Settings and content live in the database, which makes environment synchronisation awkward. Change settings on production deliberately rather than trying to deploy them.