With some lightweight web-releated project, I often found that pushing a particular Git revision to the production server – forming a Git to FTP bridge – could be a really convenient part of the workflow. For example editing/versioning the theme for this blog is this kind of issue.

Having a custom action pushing git to ftp at your fingertips can simplify production code deployment.
I’m using SourceTree (for Mac OSX) to manage my Git repositories, which has a “Custom Action” feature fortunately that can execute shell scripts with some parameters passed in about the current repository (actually about the current working copy).
In the meanwhile René Moser made a useful command-line tool to called git-ftp (surprisingly) to perform the same task I outlined above. I’d prefer a GUI setup, though, that is more close to my workflow.
So the only thing left is to hook up these parts together. I’m thinking of writing a step-by-step tutorial here, since I could be exhausting to get these things together for people like me without a reliable knowledge on weird terminal commands and pesky shell scripts.
0. Show hidden files.
Type into terminal (at any location):
defaults write com.apple.Finder AppleShowAllFiles YES killall Finder
1. Install git-ftp (will be installed in /usr/local/bin).
Type into terminal (at any temporary download location):
git clone https://github.com/git-ftp/git-ftp.git cd git-ftp git checkout master sudo make install
Or you can check a more complete installation guide at the git-ftp project page INSTALL.md. Not that you’ll need administrator (super user) access for the last command.
2. Add a tiny shell-script (bridge between SourceTree and git-ftp).
Grab (or create) these – gitFtpInit.sh, gitFtpPush.sh (also find gitFtpInit.bat, gitFtpPush.bat for Windows by Mools Gang) – shell script, and put it near you brand new git-ftp installation in /usr/local/bin.
Seems you have to restore the scripts’ chmod to work properly, so make them execuable using chmod.
chmod +x /usr/local/bin/gitFtpInit.sh chmod +x /usr/local/bin/gitFtpPush.sh
Thanks, Frédéric.
3. Configure Custom Git to FTP Action in SourceTree.
Open SourceTree Preferences/Custom Actions then Add.
In SourceTree preferences create a custom action by providing some basic setting.
Add a name for the action, a path to the script from step 2., then provide some parameter hooks to the script: $REPO (FTP username) (FTP password) (FTP path).
Note that you not just provide the FTP host but the full FTP path where you want to deploy your code. Something like ftp://<FTP host>/<path to directory>. Also checking Show Full Output is a good idea to see git-ftp responses/process.
4. First run (let git-ftp setup some stuff on FTP)
For the first time git-ftp need to do some setup at your FTP server. So you should run the action with the initialization script gitFtpInit.sh (only for the first time!), so change it temporary in your action definition.

For the first time, you should run the initializer script (gitFtpInit.sh) instead of the push script you’ll be using anyway.
Run the action, see it initialized, be happy.
You should undo the changes you’ve made in action definition, so write back the script name to gitFtpPush.sh, and done.
Having this you can easily push your latest state of your working copy to the FTP you specified. Be warned that git-ftp expects that no other people (nor you) is going to modify the deployed files in any other way than pushing with this tool (as you can see this stated in Limitations section of the project page).
DISCLAIMER. THE INFORMATION ON THIS BLOG (INCLUDING BUT NOT LIMITED TO ARTICLES, IMAGES, CODE SNIPPETS, SOURCE CODES, EXAMPLE PROJECTS, ETC.) IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE INFORMATION ON THIS BLOG (INCLUDING BUT NOT LIMITED TO ARTICLES, IMAGES, CODE SNIPPETS, SOURCE CODES, EXAMPLE PROJECTS, ETC.).