This isn't 100% failsafe, but the first thing I do is disable FTP and only grant limited SSH users.
I typically then setup an SVN repo (you can use GIT, Mercurial, etc) with a dev, test, and prod branch structure (prod is created, test is dervived from prod, and dev is derived from test. Developers have access to dev and test and select individuals have access to prod. Then I have a weekly/monthly/it can be scheduled to run when necessary job that will take the code in the prod branch and overwrite the website with it.
Therefore the primary way the website is changed is via your SVN repo and by pushing changes from dev to test, and then from test to prod (provided it has been tested and verified).
Granted those with SSH accounts "could" change the website directly, but the next push of prod to the website will overwrite their changes.