Use build tool (Ant, Maven, whatever) and continuous integration tool (CruiseControl, CruiseControl.rb, Hudson, etc).
Do not use hooks for deployment purposes if somebody will recommend it. Specifically in this case hooks approach is wrong because of the several reasons:
- Scaling. Hooks do not scale. It is difficult to make hook script do what they are not supposed to as, for example, deployment, which always requires some tricks to perform successfully.
- Flexibility. Hooks are not flexible enough. You need to rewrite them every time there are changes in your processes. And your corrections might break something you managed to do with hooks previously.
- Security. Are you going to store login/password for ftp/ssh deployment directly in your hook? That will be a huge mistake. You might find workaround, but it will be no good either as long as hooks are not the place for security management.
- Complexity. Deployment usually requires a lot of specific actions to do even when at first it seems that it does not. If you start to do deployment in your hook scripts, they will turn out to be swollen and unmanageable.
- Source control. You cannot put hooks under source control. If you will try to put it under source control, you will definitely regret it later as long as it is difficult to store hooks together with your project sources, in one place.
All you need to is to:
- Write build script where you describe your deployment steps
- Install continuous integration tool
- Make continuous integration tool use your build script and repository
- Configure continuous integration tool to perform build on commit
- Perform commit to the repository and see how your changes will be automatically built & deployed according to the build script you've written.
Personally I use Ant and CruiseControl.rb for the purpose you've described.
Here is the example of build script to deploy my changes over ftp protocol:
<?xml version="1.0"?>
<project name="myproject" default="deploy-local">
<property file="build.properties"/>
<target name="deploy-local">
<echo message="Deploying version ${version}" />
<delete dir="${deploy.path.local}" />
<copy todir="${deploy.path.local}">
<fileset dir="." includes="**/*" >
<exclude name=".svn/**" />
<exclude name="build.*" />
</fileset>
</copy>
</target>
<target name="deploy-remote">
<echo message="Deploying project" />
<ftp action="del"
server="${deploy.remote.server}"
userid="${deploy.remote.login}"
password="${deploy.remote.pass}">
<fileset>
<include name="${deploy.path.remote}"/>
</fileset>
</ftp>
<ftp action="mkdir"
server="${deploy.remote.server}"
userid="${deploy.remote.login}"
password="${deploy.remote.pass}"
remotedir="${deploy.path.remote}">
</ftp>
<ftp server="${deploy.remote.server}"
userid="${deploy.remote.login}"
password="${deploy.remote.pass}"
remotedir="${deploy.path.remote}"
passive="yes">
<fileset dir="." includes="**/*" >
<exclude name=".svn/**" />
<exclude name="build.*" />
</fileset>
</ftp>
</target>
</project>
build.properties
file has following content:
deploy.path.local = C:\\apache\\htdocs\\myproject
deploy.path.remote = /http/deploy
deploy.remote.server = ftp.myproject.com
deploy.remote.login = mylogin
deploy.remote.pass = mypass
I would recommend spending some time to learn basics of build management (Ant) and continuous integration (CruiseControl) to perform deployment in a most appropriate fashion. Even though it might seem little bit more complex, it is a right thing to do.