git-ftp: deploying Git commits to an FTP server
Uses Git to upload only changed files to FTP servers.
At a glance
- What is it?
- git-ftp uploads only the files that changed since the last deployment, tracking the uploaded commit in a log file on the server. It is a single Shell script for people who deploy over FTP and want Git to decide what moves.
- Who is it for?
- Use git-ftp if you deploy a Git-tracked site to an FTP or FTPS server and want to skip re-uploading unchanged files. Do not use it if you need atomic releases, a rollback command, or deployment from a working tree that keeps changing during the upload.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 42 days ago.
- What is it written in?
- Mainly Shell, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem git-ftp solves for FTP-only hosting
Plenty of hosting still hands you an FTP account and a web root, and nothing else. There is no build pipeline, no SSH, no rsync endpoint. The usual workflow is to drag a folder into an FTP client and let it overwrite everything, or to guess which files changed since the last upload. On a site with a few thousand files, the first approach wastes bandwidth and time; the second approach is where broken deployments come from, because a forgotten template or asset stays on the server in its old version.
git-ftp targets exactly that situation. It assumes your project is already in Git, and it uses Git to answer the question the FTP client cannot: which files differ from the revision that was last uploaded. The README puts it plainly: it "can save you some time and bandwidth by uploading only those files that changed since the last upload." The audience is a developer or a small team pushing a static site, a PHP application, or a theme to shared hosting, where Git is on the local machine but the server only speaks FTP.
How git-ftp decides what to upload
The mechanism is a log file on the server. According to the README, git-ftp "keeps track of the uploaded files by storing the commit id in a log file on the server." The local Git repository is the source of truth for what changed; the remote log is the record of what is already there. When you run a push, git-ftp reads that stored commit id, computes the diff between it and the current HEAD, and uploads only the files in that diff. After the transfer finishes, it writes the new commit id back to the log.
That design has a consequence worth stating: the server is stateful. The log file is not a cache you can delete casually. If it is removed or becomes unreadable, git-ftp has no way to know what was deployed, and the README offers catchup as the answer for the case where "the files are already there" but the log does not reflect it. The tool is also not a build system. It uploads files as they exist in the specified commit, so anything that must be generated before deployment has to be generated and committed first.
The README also documents a real constraint on this model. git-ftp "was not designed as centralized deployment tool," and while a commit is being pushed, "all files belonging to that revision must remain untouched until git-ftp has successfully finished the upload." If a build process rewrites files mid-upload, the bytes that land on the server may not match the commit that was recorded. That is a correctness problem, not a performance one.
Installing git-ftp and running your first git ftp init
git-ftp is a single Shell script named git-ftp, which is why Git picks it up as a subcommand once it is on your PATH. The repository ships a Makefile, and INSTALL.md is the file the README points to for per-system instructions. The Makefile documents the available targets: make install installs the script, make install-man installs the man page, and make install-all does both. The default prefix is /usr/local, so the script lands in /usr/local/bin.
make install
# installs git-ftp into /usr/local/binIf you would rather not install it system-wide, the script itself is the artifact; putting it somewhere on your PATH and making it executable achieves the same result, which is what the Makefile's install rule does with mode 0755.
Configuration is per repository, stored in Git config. The README gives this example, and the keys are git-ftp.url, git-ftp.user and git-ftp.password.
git config git-ftp.url "ftp://ftp.example.net:21/public_html"
git config git-ftp.user "ftp-user"
git config git-ftp.password "secr3t"With credentials set, the first deployment is either an init or a catchup. Use init when the server directory is empty and you want every tracked file uploaded. Use catchup when the files are already on the server and you only want git-ftp to record the current commit as deployed, without transferring anything. The README shows both as one-liners.
git ftp init
# or, if the files are already there
git ftp catchupAfter that, the loop is ordinary Git work plus one command. You commit locally, then push.
echo "new content" >> index.txt
git commit index.txt -m "Add new content"
git ftp pushThe README shows the output for that push: a line reading "1 file to sync", a buffered-upload line naming index.txt, then "Uploading ..." and a final line reporting that the last deployment changed to a commit id. If something goes wrong, the README says to add -v or -vv for more output, and points to the manual in man/git-ftp.1.md for further options.
Where git-ftp is the wrong tool
The strongest limitation is the one the project states about itself: it is not a centralized deployment tool. That rules it out for teams where several people or CI jobs deploy to the same server concurrently. Two pushes racing against the same remote log can leave the log pointing at a commit whose files are not what the server actually holds, and there is no locking described in the README to prevent it.
The second limitation is platform testing. The README says the maintainer is "very limited in testing on Windows and OS X" and asks for help fixing bugs there. That is an honest statement about where confidence is thin, and it matters if your developers are on Windows, since the tool is a Shell script and depends on the surrounding environment behaving. If your deployment target offers SSH, rsync or a Git-based deploy hook, those give you atomic releases and a rollback path that git-ftp does not describe. git-ftp is for the case where FTP is the only door into the server.
One more boundary: the README does not document a rollback command. It mentions that you can "go back in the Git history to upload an older version," which is a checkout-and-push workflow, not a server-side revert. Recovering from a bad deployment means checking out the older revision locally and pushing it, which uploads the older file contents again.
git-ftp compared with a Git-driven deploy pipeline
The natural alternative is to skip FTP entirely and let a Git host or CI service deploy for you. The README itself links to a GitHub Actions action for FTP deploy and a Bitbucket Pipelines video tutorial, which shows the intended shape of that setup: the same git-ftp script runs inside a runner, and the FTP credentials live in the CI service's secret store rather than in your local Git config.
The difference in approach is where the state lives. In the CI variant, the runner clones the repository fresh on every run, so there is no local history to diff against; the remote log file is the only thing that tells git-ftp what was already uploaded. That makes catchup and the log file even more central to correctness. In the local variant, your working repository holds the history and the log file is a small piece of remote state. If you already have a deploy mechanism that ships a release directory and swaps a symlink, git-ftp is a different model: it mutates files in place under the web root, one changed file at a time, rather than publishing a complete release atomically.
Maintenance, licence and upgrade cost
The repository is not archived, and its last push was on 2026-08-19. The most recent tagged release listed is 1.6.0 from 2020-02-03, described as better error handling; before that, 1.5.2 in 2019 used Git's new core.hooksPath config, and 1.5.1 in 2018 fixed FTPES support. The gap between the latest release and the latest push is worth noting if you depend on packaged versions: distribution packages may lag the master branch, and the changelog in CHANGELOG.md is where release-level changes are recorded.
Upgrade cost is low by construction. The deliverable is one Shell script, and the Makefile's uninstall target simply removes it from the bindir. There is no daemon, no database migration, and no server-side component to update. The one thing an upgrade can affect is the remote log format, so deploying with a new version against a server whose log was written by an old one is the case to test on staging first.
The licence is GPL-3.0, stated in the README's copyright section and in the LICENSE file. If you embed the script in a product you distribute, the copyleft terms of that licence are the thing to read; that is a question for your own legal review, not something this article can settle.
Editorial conclusion
Use git-ftp if you deploy a Git-tracked site to an FTP or FTPS server and want to skip re-uploading unchanged files. Do not use it if you need atomic releases, a rollback command, or deployment from a working tree that keeps changing during the upload. Before adopting it, verify on a staging server that your host supports the protocol you configure in git-ftp.url, and check whether your server allows the log file git-ftp writes to be read back, because that file is the only record of what was deployed.
Frequently asked questions
Why is FTP no longer used?
The README does not argue for or against FTP as a protocol; it presents git-ftp as a way to upload changed files when an FTP server is what you have to deploy to. The tool itself supports the FTP URL form shown in its setup example, and release 1.5.1 fixed FTPES support.
How do I create an FTP connection for git-ftp?
git-ftp does not create an FTP account; the README assumes one exists and shows how to point the tool at it. You set git-ftp.url, git-ftp.user and git-ftp.password in Git config, with the URL carrying the host, port and target directory.
How do I move a file in Git with git-ftp?
The README describes uploading files that changed since the last upload, not moving them within Git. You commit locally and run git ftp push, and the changed files are buffered and uploaded, with the last deployment updated to the new commit id.
Does anyone still use FTP?
The README does not discuss FTP adoption. It addresses the case where you already have an FTP server and use Git, offering git ftp init for a first upload and git ftp catchup when the files are already there.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/git-ftp-git-ftp)