Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using git-flow in a multi-stage deployment

Drawing a blank with finalizing my deploy scheme here. After posting this question: Migrating a production site with no VCS at all to Git, I've got the gist of deploying to a local repo down.

My local development server has a git-flow repository on it that I can push to and it will update an external worktree.

I have my repo set up with git-flow and here's what my origin remote looks like:

$ git remote show origin
* remote origin
  Fetch URL: ssh://user@host/var/git/dev/repo.git
  Push  URL: ssh://user@host/var/git/dev/repo.git
  HEAD branch (remote HEAD is ambiguous, may be one of the following):
    develop
    master
  Remote branches:
    develop tracked
    master  tracked
  Local branch configured for 'git pull':
    master merges with remote master
  Local refs configured for 'git push':
    develop pushes to develop (up to date)
    master  pushes to master  (up to date)

What I attempted to do, was set up 2 pseudo-environments. One for staging and one for production. I want to have them behave as follows:

git push staging #pushes to remote staging repo with a post-receive hook "git checkout develop -f"

git push production #pushes to remote production repo with a post-receive hook "git checkout master -f"

This way, we can develop locally and push to our little internal development server and have all the history. Then when we're clear for staging/production, we just push out the appropriate branches.

I tried creating bare repos with separate work trees like I did with the development server (see my link at the beginning of the post), and simply did:

git push staging develop
git push production master

And here are the remotes, respectively:

$ git remote show staging
* remote staging
  Fetch URL: ssh://user@host/var/git/dev/staging.git
  Push  URL: ssh://user@host/var/git/dev/staging.git
  HEAD branch: develop
  Remote branch:
    develop tracked
  Local ref configured for 'git push':
    develop pushes to develop (up to date)

$ git remote show production
* remote produdction
  Fetch URL: ssh://user@host/var/git/dev/production.git
  Push  URL: ssh://user@host/var/git/dev/production.git
  HEAD branch: master
  Remote branch:
    master tracked
  Local ref configured for 'git push':
    master pushes to master (up to date)

So, in theory, we can use git-flow internally, track the develop branch and push it out for other departments to view/QA. Then we can do our releasing internally, and push the changes to staging and then simply push the master branch to production.

I guess my question is - am I going about this the right way? I am a real novice when it comes to git and git-flow. I've pored over all the resources available and this is the best I could come up with so far.

Any insights from folks who are using git-flow in multi-stage deployment would be greatly appreciated.

like image 466
James Avatar asked Aug 31 '11 19:08

James


2 Answers

Here's what I ended up doing, this is a slight variation of what I proposed above and stems from another question I posted here: Deploy git branches

One post-receive hook to rule them all.#

Post receive hook looks at the refname:

If the refname = "refs/heads/master" (pushing to master branch):

echo "Updating production document root..." GIT_WORK_TREE=/data/hosts/production/web/ git checkout -f master echo "Production document root updated" 

Then I use the post-receive-email hook that came with git to send a nice little email about the commit. Currently developing an API for our issue tracker so that we can close issues with commits etc.

The same happens when refname = "ref/heads/develop" (pushing to develop):

Bonus Points

3 branches - production, develop (staging), and an issue tracker branch for small-ish projects. Sometimes though, we have larger projects that require long-term dev and can't get in the way of day to day dev.

You can modify the post-receive hook to look for refs/heads/(.*?), which would fire if you did something like git push -u crazy-experimental-long-term-branch

This lets us create a long term project branch, push it up with -u, and have a subdomain automatically set up at crazy-experimental-long-term-branch.site.com with some simple scripting.

Day to day dev occurs, issue resolution rolls and gets greenlit (with weekly scheduled merges to production), and crazy experimental long term branches can be merged in when ready.

I'm sure I am offending the sensibilities of the Git Gods with this deployment strategy, but we've been successfully deploying a large-scale application with this method for about 5 months and aside from the occasional merge conflict, haven't had any issues.

Hope this is helpful.

like image 105
James Avatar answered Oct 11 '22 08:10

James


If you only want to deploy the master, you can use following snippet:

read oldrev newrev refname
branch=$(git rev-parse --symbolic --abbrev-ref $refname)

if [ "$branch" = "master" ]; then
    echo "Deploying new master"
    GIT_WORK_TREE="$DEPLOYDIR" git checkout -f master
    echo "Finished."
else
echo "  No commit to master. Deploying nothing."
fi
like image 25
Roman Avatar answered Oct 11 '22 06:10

Roman