I feel, Your exact method might be useful for Test servers. I won't want all my git pushes reflect on the live server. For deployment, I think it's better if one maintains the post-commit-hook to a certain branch, named, say, "Deploy". Any push to Deploy branch would make it deploy maybe?
That sounds exactly like a system I set up with Jenkins a while back. It would deploy to a test server and run the tests from any branch. If you pushed to the deploy branch, it would deploy to the real server assuming all the tests passed.
The actual deploying and testing was all done with Fabric, but the idea was the same.
I think that's a pretty good case for using a CI system like Jenkins, especially because it's really easy to set up. It didn't support Git by default, but there was a plugin that was both easy to install and fairly comprehensive.
I know it's not ftp over ssh. I meant what I said in the context of the original comment; if ssh is the ftp replacement, then there is an application which transfers files over ssh with commands similar to those of ftp, which is sort of a compatibility mode to help ftp users migrate to ssh. (Although it is a new protocol from the ground up, it is usually used as a subsystem of ssh, thus using the same passwords and authentications and stuff.)
I just found out recently that SCP is horribly slow when transferring lots of small files. I found a blog post showing how to send compressed tarballs over SSH and it worked really well:
This tutorial is missing a lot of steps. It therefore expects the user to know how to use Git in order to consistently commit and push their changes under such a scheme. If the reader is a self-sufficient Git user (i.e. doesn't need a full step-by-step walkthrough), they wouldn't need this tutorial.
Anyhow, this scheme sort of old hat for Git users. Most of us require a build to deploy code, which generally results in SCM-polling continuous integration solutions like Jenkins to fully automate the preparations required to run new code.
This blog post sort of suggests a WordPress crowd's version of continuous integration. Go ahead and use it for a blog theme, or a set of assets. If you're doing this for a web application, you're probably doing something wrong.
Hello, I am learning git. Even if this tutorial does not comply to the rules of the art or omit basic git knowledge, it fits exactly my actual learning level. I have read the most basic tutorials and this kind of "almost second" level tutorial is perfect to have a better understanding of how pieces fit together.
The very first sentence is why Git is not the new FTP:
> First, create a directory on your server and initialize an empty git repository.
The number of people who deploy sites via FTP who also have SSH access and the ability to install Git on their hosting is small. Most people deploying to the web do not control their own servers.
I almost got kicked off of my old shared host for installing Java on my machine after I faxed them a copy of my driver's license to get SSH access. Got myself a shiny new VPS a few months ago and haven't looked back. I can finally do things I could only dream about with the shared host.
saying that git is the new ftp is to my mind not correct.
I read that git doesnt handle big files very well the coder from the backup tool "bup" has written. That was why he invented bup.
Correct me if I am wrong, I would really love to replace ftp with git.
afaik serving websites from your home dir is a bit odd, since the user running nginx/apache shouldn't have access to it, something like /var/www is way more common.
and asuming you don't just use git for deployment but also for it's core purpose version control you should setup the origin to the actual origin and name the remote where you push to accordingly (production, dev, test, staging) and you shouldn't set it as the default push, to avoid excedently deploying when you just wanted to checkin the code to the origin repo!
I built a system to deploy to our test servers that uses a git repository on the test server, clones the repo into a named folder, and checks out a specific branch. QA is able to use a webpage to select a branch, which is automatically checked out in its own folder and a subdomain or cookie is used to do isolated testing of that branch.
So for us, git is an important part of our deployment process, though there's more that goes on especially for production deployments.
I think posts like this tells you only part of the story. Ops it is not just pushing code live.
I'd be great they explain how to know which code is live (ie. tag "releases"), how to revert to a previous version (ie. something went wrong), potentially something needs to be restarted, etc.
Once, I had to maintain a website on godaddy, where I only had ftp access. I hated it. We would have interns working on it, and giving them the ftp password sucked.
Having git as a proxy, hooked to sync master on ~/www and staging on ~/www/staging was awesome.
If you want it: https://github.com/ezyang/git-ftp
I'd question the assumption that ftp was ever the old ftp, if by "ftp" we mean "deployment channel to production services". As soon as your web site is complicated enough to need a database, you have database migrations or their moral equivalent to worry about as part of the upgrade process, an simply dumping files in a directory somewhere doesn't cut it
I agree the blog post should warn about it - but it can be perfectly secure if you do it correctly. I usually put all public files inside a directory inside the repo, e.g. public_html, and/or block access to dot-files altogether in the server configuration. E.g. in Apache 2:
<Files ~ "^\.">
Order allow,deny
Deny from all
</Files>
Using post-commit hooks to handle your deployment for you can have undesired effects if your scripts aren't perfect.
I would recommend looking into continuous integration over this method. I've been using TeamCity for just over a year and it is fantastic for a staging environment.
Seriously, try it. History expansion works on input lines separated by the user asking the shell to run them, it can't cross reference command arguments on the same command line.
I have tried both, the difference is only that !$ echos the expanded command, while $_ simply runs the expanded command; both create a directory and cd into it.
Err, what about rsync? My blog is versioned with git, but compiled with USSM¹. I don't want to version the generated html code, so I deploy it with a one line shell script that just calls rsync through ssh. Simple, and fast.
So in my case, rsync looks better than git at deployment. I can't imagine a scenario where the reverse is true. Does someone have a counterexample?
Unfortunately, this doesn't take into account the fact that stuff you keep in your development repository is almost never identical to stuff you want on your deployment server. There are files you keep in the former but not necessarily want/need in the latter (unit tests, documentation, etc.). Similarly, there are stuff to be put on deployment server which don't want to clutter your dev repository, like compiled CSS/JS assets.
As other have said, deployment should really be done by continuous integration server, and preferably using a protocol that's designed for transmitting files, not version control.
git is closer to rsync than to ftp. scp and ftp are file transfer protocols, while git and rsync are higher-level systems that can use other underlying file transfer protocols
Every time someone comes up it with a "cool" way to deploy via Git, it turns out their definition of "deployment" is nothing more than dumping something on a server. It completely ignores every aspect of deployment other than putting the files somewhere else, which is 5% of the work and 1% of the complexity of deployment.
That's not even a sufficient professional scenario for anything but the simplest of non-essential website. Hell, this won't even do for the simplest of WordPress sites.
The commonalities between SFTP and FTP end with the three letters in the acronyms. SFTP, unlike FTP with its passive mode and whatnot, is actually a decent protocol.
rickmb did not come even remotely close to specifying on which grounds he was asking his question. He might be a proponent of "if it's not automated [via capistrano/fabric/etc...] it's not deployed" for all I know.
I deploy via git with a more complex post-update hook that runs tests before pushing into the production repo and all the other commands needed for my Django setup.
I am currently trying to figure out a more clever way to deploy my code. I would love if you would share some thoughts on some general strategy and possible tools. I am using jenkins and git.
I use Capistrano to deploy PHP web apps and I love it. It basically checkouts stuff from the git repo, minifies and bundles the JS files, uploads the assets to the CDN and tags the repo with the version string. Though Capistrano has been traditionally a ruby deployment tool, it works well for any type of deployment. You just need to override or not use some of the Ruby-specific stuff. Deploying to multiple servers is ridiculously easy with Capistrano.
To be honest, most of them do so because it's the only option present on most shared hosting platforms. (S)FTP is for most of us the only option when deploying a simple site to the client's hosting.
Ofcourse it would be cool if all of our clients would host on a PAAS platform like Orchestra or PHPFog but that's not the case by a long shot i'm afraid.
A year and a half ago I worked at a place that had a Deployment Spreadsheet.
Each file was carefully FTP'd from the shared development area to the live site, and then marked off on the sheet with the date that it had been deployed, and with what feature.
Each new deployment meant either adding a new set of rows to the spreadsheet for a new feature, or for updates to existing features going back and finding an earlier instance of the file in the list and bumping the date on that.
Because of the shared nature of the CMS across different websites, we couldn't svn up in the CMS directory without destroying the current known state of the site. We also couldn't svn up outside of the subdirectory we were working on, as everyone else working on that site was working off the same network share. Everything was done very gingerly.
The day one of the developers came up with a method to take a list of files from the spreadsheet, tar them up and FTP them to the server for later extraction, he was overjoyed and very, very proud.
I got out of there, swore off PHP and its community entirely. I got tired of checking for a baseline of automated deployment, automated testing, version control, and individual dev systems at every single job I applied for; Ruby people don't look at you funny when you mention these things.
Addendum: I personally know a developer currently working for a famous local radio brand who directly works on the live website network via an FTP plugin. He has to contend with other developers dumping the contents of archives directly into his public folder.
FWIW, this is essentially how Oracle ships updates for their enterprise business systems: you get a tar file and a README telling you which files get copied to which spots on which servers.
That shitty deployment experience has nothing to do with PHP. There are plenty of valid reasons to move to Python or Ruby, but better deployment stories aren't one of them. Objectivity seems to be in short supply here on HN.
Isn't the ecosystem always trotted out while defending PHP, as well as its 'accessibility' to amateurs? Well, those amateurs are part of the PHP ecosystem, and you'll have to put up with that... or not.
heretohelp made the point better than I did, but I explained my thoughts on that with this sentence:
I got tired of checking for a baseline of automated deployment, automated testing, version control, and individual dev systems at every single job I applied for; Ruby people don't look at you funny when you mention these things.
It's about expectations. I tried really hard to find a place that had all these in the PHP world. In the Ruby world (for example), it's a given.
(I have only ever encountered one PHP shop during my rounds interviews that did automated testing... But they used CVS for version control. The very first Ruby shop I interviewed had all of the above, and treated it like they were no big issue.)
* Track changes to the repository as a whole, instead of per file. I care most about stepping through revisions of a project; inspection of the history of a particular file is a secondary concern for me, but is all that CVS can do. A "project" for me is usually a set of files that are interdependent to greater and lesser degrees.
The best you get with CVS for tracking the versions of all the files in a repository is manually creating tags all the time. With Git, Subversion, Mercurial, Bazaar, etc you get this for free; it's how these tools work.
(As an aside, DOS is also a proven operating system. For varying values of "proven".)
I couldn't agree more. Deployment via SCM tool is a terrible idea. The first thing to do when starting a project, no matter how small, is to set up a continuous integration server with a clear build and deploy process.
You can deploy Tomcat apps using a post-commit hook as well. Add your server as a non-origin remote, and it's a quick way to update a Clojure/ring site. For added predictabIlity, you can deploy a specific branch.
This bit has completely lost me. Why on earth would you want to do non-trivial munging in a post-commit hook instead of just writing and running a "deploy" script like everyone else does. You can run that over ssh, even, preserving the "fire once" behavior of doing a git push from the build system.
Copying a .war to /var/lib/tomcat/webapps and restarting tomcat is non-trivial? Perhaps your deploy script is more complicated than it should be. I don't understand your distaste with deploying via git over ssh instead of bash over ssh.
You haven't needed to restart Tomcat since at least Tomcat 5.5, if not earlier. Tomcat automatically polls for changes to the WAR file and updates accordingly.
That's the theory, but I've found many reasons to restart that I just do it automatically these days. The reasons are not limited to stupid webapps, jni, log4j stuff that outlives a deployment and ends up consuming all of PermGen.
An interesting point. I get the part about "stupid webapps" (e.g. loading a configuration file once and never checking it again), but I find the PermGen part surprising. Would you care to provide more detail? I thought that PermGen was garbage collected in modern JVMs; furthermore, wouldn't the new version of the application still use (roughly) the same classes/methods and thus (roughly) the same space?
This happens because Tomcat is unable to release some classes from the classloader. So every time I load a new WAR lets say I am using Spring. Tomcat doesn't remove the old Spring Jar from the classloader and just loads a second one for my updated WAR. After doing this a few times (Depending on the size of your app, permgen size and how many 3rd party libraries you have) tomcat will throw a permgen error. There is nothing Tomcat can do about this. It is the classloaders problem. Also it is not recommended to "hot deploy" to a production environment.
I've done some more reading on this issue, and I don't think what you are saying is correct.
First, class loading is more granular than JAR files. From what I can tell, the JARs are just repositories (if you will) for the actual class data. Once a class has been loaded from a JAR, it is distinct from it, and there is no need to keep the whole JAR in memory.
Second, there are many class loaders at play, not just one. At the least, there will be one class loader for Tomcat and one class loader for each web app. This is necessary to keep web apps from breaking each other (and Tomcat!) by loading incompatible versions of classes.
Third, once a class is no longer used (i.e. there exist no objects that are instances of it) it can be garbage collected, and will be if more PermGen space is needed.
Fourth, once a web app is unloaded, its class loader is no longer needed, and it too can be garbage collected (along with any memory it was using to store the aforementioned JAR files, although presumably that memory would be outside of PermGen).
Taking all of this into account, one might (like me) naively presume that once you unload a web app, all of its objects will no longer be referenced, and this will propagate up the tree of references (servlet -> object -> ... -> object -> class) until nothing from that app remains.
HOWEVER, this assumes that references exist in a tree. A singleton class would cause problems: it stores a reference to an object of its own type. This creates a circular reference pattern (class X -> object -> class X) and keeps both class and object in memory.
A possible solution might be to associate each class with the web app that loaded it, then when you unload a web app, you can walk through all of the classes it loaded and null out all of their static fields. This will allow the referenced objects to be garbage collected, and in turn, the classes of those objects.
But this is probably much easier said than done (it may even be impossible due to limitations on the JVM), and there are probably other issues I'm not even aware of and thus not considering. Never mind JNI, which just adds even more fun to the mix.
So ultimately I must agree with the recommendation to restart Tomcat when you're deploying web apps. From a developer perspective, I would also recommend eliminating static data in your libraries and web apps as much as possible.
I use Transmit to FTP updated files to my web server. Then I send smoke signals to my colleagues to inform them of the changes, and document the updates on a papyrus using quill and ink. Should I be doing it differently?
Parchment only.
Papyrus has a standing export restriction from the issuing superpower (Egypt circa 200BC), so if it becomes a superpower again you could be extradited for disobeying the law of a that foreign country that attempted to force an unfair business advantage to the rest of the world.
I actually assumed "smoke signals" was some sort of Mac app that I didn't know about (it actually sounds like it could be a 37 Signals product). I even wondered if "papyrus" was a team-management wiki or the like. Then I got to "quill and ink" and realized you were joking.
More complex deployment processes can be kicked off in the post-receive hook.
I think it's useful to have deployment integrated with your SCM. You have a complete history of deployments. You can easily roll back to any version. You can deploy from any machine which has your SCM tool installed.
Just a bit feedback on the blog: The background image was very distracting for me. My eyes were always wandering off from the text. Not sure if that's just me or if others had that problem too.
Had similar problem with a site called TVCatchup. They stream free TV in the UK. Their player sits in the middle of the page and that is surrounded by an advertising border. Nothing else on the page of consequence. What I found was that I found it very hard to focus on the player in the middle. Often I would get a headache watching. Told the admins, who didn't want to know. Basically I got an angry "Foxtrot Oscar". Ended up using an ad blocker until they found a way to defeat that. Now I don't use the site any more.
Completely off topic, but TVCatchup provide an XBMC plugin which completely avoids the advertising they add. No idea why, since it presumably destroys their business model, but it's great.
Coderwall forces you to upload an image, then it "hipsterizes" it (their words, not mine). From what I can tell, this involves significantly reducing the size of the image, increasing the saturation and local contrast, and then stretching and blurring it.
As a photographer, this is quite annoying, because it's hard to predict what something will look like. I'll try to find a photograph of mine that'll stand up to being "hipsterized" better.
When git software is easy for ordinary people to use and install on windows, easy enough that people are using it to share porn and pirated material, then maybe it will be like ftp.
As it is to run git on windows you, best case, have to install a lightweight nix OS. Cygwin mingw,whatever. I think we techies and power users don't realize how messed up that is if you want git to be more than a program for programmers. Ftp was a protocol, you could make a native client for everything. Git is a great tool, but not yet comparable to ftp.
You can have git separate the .git directory and the working directory by setting GIT_WORK_TREE and GIT_DIR in the post-receive hook. I usually put the git directories in /var/local/git, and I have some scripts to automate everything, but essentially I use this mechanism for certain projects (and for testing).
Surely the entire project doesn't consist of world-readable files? There's likely to be a htdocs or wwwroot subdirectory in there alongside .git that apache/nginx point to. Then, you have an extra level of breathing room for other files for the site (config files, session data, user uploads, ...)
145 comments
[ 3.3 ms ] story [ 272 ms ] threadThe actual deploying and testing was all done with Fabric, but the idea was the same.
I think that's a pretty good case for using a CI system like Jenkins, especially because it's really easy to set up. It didn't support Git by default, but there was a plugin that was both easy to install and fairly comprehensive.
> SFTP is not FTP run over SSH, but rather a new protocol designed from the ground up by the IETF SECSH working group.
http://en.wikipedia.org/wiki/SSH_File_Transfer_Protocol
ssh username@from_server "tar czf - directory_to_get" | tar xzvf - -C path_to_save
Anyhow, this scheme sort of old hat for Git users. Most of us require a build to deploy code, which generally results in SCM-polling continuous integration solutions like Jenkins to fully automate the preparations required to run new code.
This blog post sort of suggests a WordPress crowd's version of continuous integration. Go ahead and use it for a blog theme, or a set of assets. If you're doing this for a web application, you're probably doing something wrong.
Thank you Kerrick Long
What if we go to http://yoursite/.git or http://yoursite/.svn ?
Often we get free passwords and other information.
> First, create a directory on your server and initialize an empty git repository.
The number of people who deploy sites via FTP who also have SSH access and the ability to install Git on their hosting is small. Most people deploying to the web do not control their own servers.
Correct me if I am wrong, I would really love to replace ftp with git.
But the post is about deployments and not about transferring files.
and asuming you don't just use git for deployment but also for it's core purpose version control you should setup the origin to the actual origin and name the remote where you push to accordingly (production, dev, test, staging) and you shouldn't set it as the default push, to avoid excedently deploying when you just wanted to checkin the code to the origin repo!
So for us, git is an important part of our deployment process, though there's more that goes on especially for production deployments.
I'd be great they explain how to know which code is live (ie. tag "releases"), how to revert to a previous version (ie. something went wrong), potentially something needs to be restarted, etc.
http://lifehacker.com/5821145/how-to-set-up-a-file+syncing-d...
Isn't that what FTP is most known for - being insecure?
I would recommend looking into continuous integration over this method. I've been using TeamCity for just over a year and it is fantastic for a staging environment.
[1]: http://www-cs-students.stanford.edu/~blynn/gitmagic/
http://try.github.com/
http://www.gnu.org/software/bash/manual/bashref.html#Word-De...
(I'm running OS X, FWIW)
&& in OS X seems to put the left side into history and works as I described, but it didn't work when I tried it in Ubuntu 10. $_ works in both.
So in my case, rsync looks better than git at deployment. I can't imagine a scenario where the reverse is true. Does someone have a counterexample?
[1] My home-made Jekyll clone: http://loup-vaillant.fr/projects/ussm/
My website is stored in mercurial currently, and when I push to the server it runs bundle and compiles the site.
As other have said, deployment should really be done by continuous integration server, and preferably using a protocol that's designed for transmitting files, not version control.
That's not even a sufficient professional scenario for anything but the simplest of non-essential website. Hell, this won't even do for the simplest of WordPress sites.
BTW, who on earth still uses FTP?
Does sftp[0] count?
[0] http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13
I am currently trying to figure out a more clever way to deploy my code. I would love if you would share some thoughts on some general strategy and possible tools. I am using jenkins and git.
Ofcourse it would be cool if all of our clients would host on a PAAS platform like Orchestra or PHPFog but that's not the case by a long shot i'm afraid.
Each file was carefully FTP'd from the shared development area to the live site, and then marked off on the sheet with the date that it had been deployed, and with what feature.
Each new deployment meant either adding a new set of rows to the spreadsheet for a new feature, or for updates to existing features going back and finding an earlier instance of the file in the list and bumping the date on that.
Because of the shared nature of the CMS across different websites, we couldn't svn up in the CMS directory without destroying the current known state of the site. We also couldn't svn up outside of the subdirectory we were working on, as everyone else working on that site was working off the same network share. Everything was done very gingerly.
The day one of the developers came up with a method to take a list of files from the spreadsheet, tar them up and FTP them to the server for later extraction, he was overjoyed and very, very proud.
I got out of there, swore off PHP and its community entirely. I got tired of checking for a baseline of automated deployment, automated testing, version control, and individual dev systems at every single job I applied for; Ruby people don't look at you funny when you mention these things.
Addendum: I personally know a developer currently working for a famous local radio brand who directly works on the live website network via an FTP plugin. He has to contend with other developers dumping the contents of archives directly into his public folder.
(For context, this is all in Sydney, Australia.)
virtualenv/rvm are the standard, using git is the standard, fabric/capistrano for pushing/provisioning is standard.
This is not the case for PHP, the vast majority are using graphical FTP clients to manually overwrite files.
I got tired of checking for a baseline of automated deployment, automated testing, version control, and individual dev systems at every single job I applied for; Ruby people don't look at you funny when you mention these things.
It's about expectations. I tried really hard to find a place that had all these in the PHP world. In the Ruby world (for example), it's a given.
(I have only ever encountered one PHP shop during my rounds interviews that did automated testing... But they used CVS for version control. The very first Ruby shop I interviewed had all of the above, and treated it like they were no big issue.)
Oh the horror! A proven source-code control system.
M-x My-lawn-remark$
* Track renames of files.
* Track changes to the repository as a whole, instead of per file. I care most about stepping through revisions of a project; inspection of the history of a particular file is a secondary concern for me, but is all that CVS can do. A "project" for me is usually a set of files that are interdependent to greater and lesser degrees.
The best you get with CVS for tracking the versions of all the files in a repository is manually creating tags all the time. With Git, Subversion, Mercurial, Bazaar, etc you get this for free; it's how these tools work.
(As an aside, DOS is also a proven operating system. For varying values of "proven".)
First, class loading is more granular than JAR files. From what I can tell, the JARs are just repositories (if you will) for the actual class data. Once a class has been loaded from a JAR, it is distinct from it, and there is no need to keep the whole JAR in memory.
Second, there are many class loaders at play, not just one. At the least, there will be one class loader for Tomcat and one class loader for each web app. This is necessary to keep web apps from breaking each other (and Tomcat!) by loading incompatible versions of classes.
Third, once a class is no longer used (i.e. there exist no objects that are instances of it) it can be garbage collected, and will be if more PermGen space is needed.
Fourth, once a web app is unloaded, its class loader is no longer needed, and it too can be garbage collected (along with any memory it was using to store the aforementioned JAR files, although presumably that memory would be outside of PermGen).
Taking all of this into account, one might (like me) naively presume that once you unload a web app, all of its objects will no longer be referenced, and this will propagate up the tree of references (servlet -> object -> ... -> object -> class) until nothing from that app remains.
HOWEVER, this assumes that references exist in a tree. A singleton class would cause problems: it stores a reference to an object of its own type. This creates a circular reference pattern (class X -> object -> class X) and keeps both class and object in memory.
A possible solution might be to associate each class with the web app that loaded it, then when you unload a web app, you can walk through all of the classes it loaded and null out all of their static fields. This will allow the referenced objects to be garbage collected, and in turn, the classes of those objects.
But this is probably much easier said than done (it may even be impossible due to limitations on the JVM), and there are probably other issues I'm not even aware of and thus not considering. Never mind JNI, which just adds even more fun to the mix.
So ultimately I must agree with the recommendation to restart Tomcat when you're deploying web apps. From a developer perspective, I would also recommend eliminating static data in your libraries and web apps as much as possible.
I use Transmit to FTP updated files to my web server. Then I send smoke signals to my colleagues to inform them of the changes, and document the updates on a papyrus using quill and ink. Should I be doing it differently?
I've also found that using parchment makes updates more durable as they weather better.
I think it's useful to have deployment integrated with your SCM. You have a complete history of deployments. You can easily roll back to any version. You can deploy from any machine which has your SCM tool installed.
Sometimes this matters:
http://stackoverflow.com/questions/6554910/i-am-failing-to-r...
(Yes, it's a hack.)
But this doesn't work for Mule; for some directories it autodetects and attempts to run it (whatever that means for that directory).
Had similar problem with a site called TVCatchup. They stream free TV in the UK. Their player sits in the middle of the page and that is surrounded by an advertising border. Nothing else on the page of consequence. What I found was that I found it very hard to focus on the player in the middle. Often I would get a headache watching. Told the admins, who didn't want to know. Basically I got an angry "Foxtrot Oscar". Ended up using an ad blocker until they found a way to defeat that. Now I don't use the site any more.
As a photographer, this is quite annoying, because it's hard to predict what something will look like. I'll try to find a photograph of mine that'll stand up to being "hipsterized" better.
As it is to run git on windows you, best case, have to install a lightweight nix OS. Cygwin mingw,whatever. I think we techies and power users don't realize how messed up that is if you want git to be more than a program for programmers. Ftp was a protocol, you could make a native client for everything. Git is a great tool, but not yet comparable to ftp.