git website update strategy – how to sync dev and live repositories?

Here is how I have been constructing my git-powered-website update and backup strategy:

I have SSH access to the Linux VPS where the website is hosted. Here is what I did:

  • Deploy a project using Git push
  • How to diff/merge changes to a deployment project file
  • How do you avoid storing passwords in version control?
  • Run batch scripts on a remote server (windows) from jenkins
  • Cannot push to heroku - bundler fails
  • Magento staging and production
  • 1) AT THE WEBSITE SERVER – Created a git repo, at the proper website folder (one level before public root):

    cd /path/to/website
    git init
    git add -A
    git commit -m "Website as of today."
    

    2) AT THE BACKUP SERVER – Created a mirror repo, for backup purposes, at another VPS:

    git clone --mirror ssh://user@example.com/path/to/website website_backup
    

    Note that a mirror repo is also a bare repository (no checked out working tree).

    3) SET UP CRONJOBS – One at the website server, to absorb wesbite file system changes (changes can be done by the scripts, by FTP, etc). It runs the following bash script, daily:

    #!/bin/bash
    date=$(date +%d/%m/%Y)
    cd /path/to/website
    git add -A -v
    git commit -m "Changes done at to website at ${date}"
    exit 0
    

    This way, the live website changes are committed to the repository master branch.

    Another cronjob is set up at the backup server. It runs the following script daily, right after the other one above:

    #!/bin/bash
    cd /path/to/website_backup
    git fetch -u ssh://user@example.com/path/to/website
    exit 0
    

    This way I have at the backup server a daily updated “backup”, which is also a git repo, allowing me to move backwards in time if necessary. I don’t need to be much afraid of losing stuff by accidental overwrites or deletions… and the process is automated!

    I receive daily a couple of e-mails from the cronjobs. It allows me to check what has been changed in the website, and to acknowledge that both cronjobs are running correctly. (Another cronjob is set up to perform the database backup.)

    4) SET UP DEVELOPMENT (LOCAL REPO + WORKING TREE) – I checked out a copy directly from the website, and then created a new local branch called “dev”:

    git clone ssh://user@example.com/path/to/website website_local
    git checkout -b dev
    

    Now, I can play with the development branch, and do my work.

    From this point, I’d like to know:

    • How to push my changes back to the live website?
    • How to get changes from the website back and merged to my development branch?

    In short: how to properly sync live site with dev branch without messing things up?

  • still being prompted for credentials after installing credential-osxkeychain
  • Find a commit on GitHub given the commit hash
  • Mirroring a repository across Github, Sourceforge and Google Code
  • Git - why are double dashes needed when running a command on a deleted file?
  • Cannot push to git repository - permission denied
  • How to detach subdirectory in Git but keep all branches
  • 3 Solutions collect form web for “git website update strategy – how to sync dev and live repositories?”

    Here is the solution I achieved to satisfy the needs of pushing my development work to “production” (live website) and also keep my local repository up to date with the changes occurring at the live website…

    To update the website is simply a matter of pushing my local development branch to the website repository…

    git push origin dev
    

    …and then, merge the changes into the live website tree. I need to SSH log in to the website server, and run the following command at the website folder:

    git merge dev
    

    This will bring the pushed changes, at “dev” branch, to the “master” branch (which is the live site current branch).

    * IMPROVING THE UPDATE PROCESS *

    To automatically run the merge, without needing to login and run the merge command from the server command line, I added a post-receive hook to the live website repository. First, I created the hook file, made it executable, and then edited the file:

    touch /path/to/website/.git/hooks/post-receive
    chmod a+x /path/to/website/.git/hooks/post-receive
    pico /path/to/website/.git/hooks/post-receive
    

    The contents of my post-receive hook file are:

    #!/bin/sh
    unset GIT_DIR
    cd /path/to/website
    echo "Merging dev changes to master branch."
    git merge --ff-only dev
    exit 0
    

    Note the –ff-only option added to the merge command. Why is it there? It is there because, being an automated process, I don’t want to have merge conflicts stored into my live website files. So, using this option, I enforce the merge to happen only if I have a clean fast-forward context. If this clean merge can’t happen, then I may log in to the server, and manually resolve the case, or solve the problem using another approach.

    * AVOIDING CONFLICTS AND SYNCHRONIZING *

    To avoid merge conflicts at the server, i.e., to ensure a successfull fast-forward merge there, it is a good idea to update the local repo with the latest changes from the remote repo. In other words: update the local development branch with latest live website changes (remote master branch), prior to pushing our changes. This could be done like this:

    git pull origin master
    

    Better yet: let’s first update the local master branch, and then merge it into the local development branch (sounds like a rebase):

    git stash save
    git checkout master
    git pull origin master
    git checkout dev
    git stash pop
    git merge master
    

    This way, our local master branch is kept in sync with the remote live website master branch, and the merge is performed 100% locally.

    * BACK TO SIMPLICITY *

    I have created an alias to facilitate things:

    git config alias.deploy '!git stash save && git checkout master && git pull origin master && git checkout dev && git stash pop ; git merge master && git push origin dev'
    

    Now, I can perform the live site update by using the “deploy” alias, like this:

    git deploy
    

    It will:

    1. Switch to local master branch
    2. Update the local master branch with the website latest committed changes (sync)
    3. Switch back to dev branch
    4. Merge the changes to the local dev branch (conflict resolution here if needed)
    5. Push the local dev branch to the remote website dev branch
    6. Having the post-receive hook properly set up at the server, it will automatically fast-forward the website repo, so the dev changes will be published to production!

    I have this setup working, and it is satisfying my current needs, which are simple.

    You might want to look at http://joemaller.com/990/a-web-focused-git-workflow/ and http://toroid.org/ams/git-website-howto for further information on integrating git and web deployment systems.

    Remember, git is not a web deployment system (though with some simple scripts it can work that way for people with simple needs).

    Or, you could just use Git and Jekyll as Github does

    Git Baby is a git and github fan, let's start git clone.