I used to work in my projects like editing a file and uploading the changed files back to the server every time when it feels like those changes are OK. But when the number of files gets bigger, I loose track which files I’ve edited. In that case I had to upload all the files again to the server via FTP.
I am using Git as my primary SCM tool. Although I wasn’t using any SCM until I realized how essential it was when developing the plugin WP User Frontend. Some clients asked me to modify the plugin to fit in their project, others asked about other requirements. So every time I had to modify that plugin to suit their needs from the beginning. And It was a pain in the ass to track where I changed for that custom work. Because I had to update the plugin again to release in the public without the custom modification. So, it was a nightmare.
Anyway, back to the topic. I thought I can easily track those changed files and can only upload those change sets and it’ll be very tiny. So I am writing the process as a future reference for myself and might help others too.
1. initialize your project
$ mkdir awesome-project
$ cd awesome-project
$ git init
As I was also working with git submodules, I’ll add the submodule to my newly created awesome project. If you don’t know what a submodule is, it’s usually an another git repository that can be used under another git project.
2. Adding git submodule
[shell]$ git submodule add ~/www/tiny-framework lib/framework[/shell]
Here I am using another git project
~/www/tiny-framework inside my
awesome-project in path
awesome-project/lib/framework. This command will clone my
tiny-framework project in the
You can skip the submodule part if you are not using any.
3. pulling changes from the framework
In case you have updated your tiny-framework project, obviously you’ll want to bring the changes to your awesome-project too, but those changes will not automatically pulled down in your awesome project. You’ve to pull it manually.
$ cd lib/framework
$ git pull
Now you’ve worked in your project and ready to deploy to the server for test or production usage. It’s time to add a remote branch to your project.
4. Add remote repo to deploy the app
Now add a remote repository to your awesome project.
[shell]$ git remote add production ssh://example.com/~/git/app[/shell]
I have shell access to my server, so I am adding the server as the remote repository. The trailing
~/git/app is the path where I’ll be pushing my local repo. In case you don’t know what the
~ sign means, it’s a shortcut to your home directory path.
5. Create the app bare repo in server
Now that you’ve added the remote repository to your local machine, you’ve to create the actual remote repository to the server. Log in to your server and create the folder and initialize the empty git repo.
$ mkdir git/app
$ cd git/app
$ git init –bare
You might have noticed, I am creating a bare repo here. There are some reasons behind why I am using bare repo.
The bare repo is not like a normal git repo, it doesn’t and will not contain any files that you’ll be pushing from your local repo. What we’ll be doing is :-
- we will create a post-receive hook in this bare repo
- we will push the local repo to this bare repo
- the post-receive hook in this bare repo will checkout our local repo and will copy our local files to another folder in the server
6. Add post receive hook to the server
Now in this bare repo, we’ll add the post receive hook to checkout our local repo
$ cd hooks
$ vi post-receive.sample
7. Add the details of the folder to clone
You’ve to add this line in the
post-receive.sample file. I am using vi/vim, you can you nano or emacs or whatever editor you want. But make sure you are providing the right path to the folder. In my case, my local repo will be copied to the
awesome-project folder in
[shell]GIT_WORK_TREE=~/public_html/awesome-project git checkout -f[/shell]
8. Rename and make executable
To make the hook work, you’ve to rename the
post-receive.sample file to
post-receive and make it executable
$ mv post-receive.sample post-receive
$ chmod +x post-receive
9. Now push the changes
Now everything is done, we are finally able to push our local git repo to the server. The files will be placed in
public_html/awesome-project folder in the server.
$ cd awesome-project
$ git push production master
Now, you might have noticed, the submodule has not been deployed to your server, why is that? Because git consider the submodule as another git repo and if you want to push the submodule too, you’ve to create an another bare repo in the server, configure the post-receive hook, adding the remote repo in the submodule and push them again as you did for your awesome-project, damn! But you’ve to do it 🙁
10. Push the submodule
Repeat the process 4 to 9 again. That means:
- cd into the “framework” folder
- add remote repo
- create bare repo in server (e.g: ~/git/framework)
- add the post-receive hook in path: ~/public_html/awesome-project/lib/framework
- push the local changes
Thats pretty much it.
Skipping the password prompt
Now your system is ready and you can always push your changes to the server. But, every time it’ll ask your ssh password when pushing the changes. You can skip this problem too. Generate a private/public key for your laptop/computer. Log in to your cpanel. Goto the
SSH/Shell Access =>
Manage SSH Keys. Then import your public key and authorize it. From now on, you’ll not be asked to enter your password every time you push you changes.
Extra: Removing a git submodule
If you want/have to remove the submodule from the project, here’s how to do it
[shell]git rm –cached path/to/submodule[/shell]
One thought on “Deploying PHP apps with git and git submodule”
If you’re interested, I’ve found an easier way to handle submodules. See my post-receive hook here: https://gist.github.com/jtsternberg/11e95ad15ac0075c040e27cccfc324f4