I'm not familiar with TFS, I used Git (CVS, and SVN previously), hence take this answer in perspective.
Managing and versioning the SQL bits have been the worst of my nightmares.
there are some tools that easy the changes management, red-gate SQL Developer Bundle, which handles comparisons, and allows connection to versioning systems too. in a lesser measure for your request you have idera SQL comparison toolset, idera's perfectionist approach to everything shouldn't be over-viewed.
Anyway in my opinion managing changes can't and shouldn't be approached as a technical thing it has to be part of the IT governance, and procedural, it requires to document and communicate among any relevant functions.
When some mini-release, hot-fix, micro-change or similar stuff happens, they have to be reflected at every other environment that needs to get it.
Of course if there is a mini-release in production and you are the middle of a UAT, you might not want to insert the mini-release in that environment. IMO, soon after the UAT you should apply the mini-release to the environment and perform a E2E QA session in order to make sure that the environment is fine.
If you read my previous paragraph you might find some problems lets say that UAT has a SP version 4 and the mini-release the same SP is 2... how do you make sure that you are not causing regressions?
This is when version control systems and merging tools come to help. Red Gate tools should also help you building the deployments.
But, I believe that governance, communications and follow the rules are the most important factor for continuous success.
The tendency today is implementing continuous integration, and build testing environments on-demand, there are in-house, hosted and on the cloud. usually they are not cheap to build and to maintain, but they pay off!
Last but not least, a couple of same of rules that you should abide when developing for SQL deployments:
- Every change script should be repeatable, for example
- before creating a procedure, check if it exists and delete it before the creation
- before any insert check that the row doesn't exists and then insert else update
- when deploying to multiple databases, every change script must make sure that you USE the proper database (here I found that synonyms are one of the best inventions since the creation of the can opener)
- change scripts should follow a sequence. for each object:
- DDL
- apply the DCL for the DDL above
- apply the DML for the table.
- I found that the best sequence in for scripts are
- create/alter Tables
- create/alter views
- refresh all views
- create/alter functions
- create/alter functions
- perform every DML.
- in every script avoid failing to the temptation of ordering the sub parts of the scripts by ABC, usually you have dependencies like FK or SP that execute other SP that make the ABC approach frustrating.