November 2013

Gavin Pickin

Git for Dummies - Pushing Code from Dev to Production with Git

Source Control

Thank you for reading along with my Git for Dummies series. We've covered a lot so far, and we're starting to use Git now, and as we continue in this series, we'll start to see a few more day to day tasks, and we'll introduce some of the bigger concepts as we face a few hurdles. Thankfully, Git makes these hurdles into more of a speed bump, and you'll see a good example today.

So far we have covered Why you should use Source Control, Not Using Source Control, amazingly you're not aloneInstalling Git on WindowsInstalling Git on Mac OSXInstalling Git on LinuxYour First RepoSetting up your first Remote Repo on BitbucketCreating your SSH Keys for Bitbucket, How to set your Default Name and Email in Git, Converting a Project into a Git Repo, today, Pushing Code from Dev to Production with Git.

Note - I'm sorry for the slight down period, busy life, busy work, but everyone knows how that goes, we'll try and keep them flowing now.

I am assuming no one is developing on Production (much) these days... it seems to be running joke on Twitter it must be a best practice if Adobe has RDS... but if you are editing live on Production... I hope using Git will help take out some of the reasons you might be doing so, because Git can make it so much easier, to deploy lots of code from a Development Server, to Production... and today we'll look at that.

So, I assume you have the following for todays walkthrough.

  • A Git repo, ours is setup on Bit Bucket, as described in an earlier session
  • A Development Server with a Clone of the Bit Bucket Repo
  • A Production Server with a Clone of the Bit Bucket Repo

Now, we're not going to cover Branches at this time, so we're going to assume we have just 1 branch, the master branch, on both servers. This is not ideal for major feature upgrades, but for small ongoing maintenance to a website project / application, this usually will suffice.

So what we want to do in this situation is take New Code, Version 3 in this example, from the Dev server, and deploy it to the production server, which is running Version 2 (over simplified to make it easier to follow). So, to start, we have 3 repos... 

  • Bit Bucket Repo - Version 2
  • Production Server - Version 2
  • Dev Server - Version 3 

So, the process would be, push from Dev to Bit Bucket Repo... and then Pull from Bit Bucket Repo to Production Server... and we are done.

Let me throw a curve ball at you... what if one of your devs had made a change? RDS, FTP, or maybe your application allowed the Users to modify files, upload content etc, and you wanted this to be as similar as possible on dev and production? A lot of my applications have this curve ball, so I'm going to show you the process I use, just to make sure that in a case like we have, where Production is really Version 2.1, we dont have any possible code clashes... especially in production.

Code Clash? Well, thats the name I've been using, but basically, when you have 2 files, Git nicely tries to merge any changes, and if you have edited them in such a way that Git cannot automatically merge them... you will get a Merge Conflict (Code Clash in my strange mind) and you will have to manually merge the file... and Git does this by creating a DIFF file, which includes both versions of the file, in the file... and you manually fix this. Long story short, a DIFF file in production leaves your code broken, and is not ideal, so you want to make sure these Code Clashes, or Merge Conflicts always happen on the Dev side... not the Production side. We'll be going into this more later, but for now, we are going to do things a particular way, to avoid issues in Production.

Ok, so now we have this situation

  • Bit Bucket Repo - Version 2
  • Production Server - Version 2.1
  • Dev Server - Version 3 (not including 2.1 update)

Since we do not want any Code Clashes on the Production Side, we want to make sure when we Pull code from the Repo to Production, it has no possible conflicts... and the way to do that, is make sure there are no new changes on Production. 
To achieve this, we are going to push all of Productions changes to the Bit Bucket Repo. 

First we do a git status to see what files have changed. This case, we see there is an update to the dsp_content_footer.cfm page. So we use Git add filename to add the file, we see its ready to commit, so we commit the file.

$ git status
# On branch master
# Changed but not updated:
#   (use "git add/rm <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#	modified:   _gmods/dsp_content_footer.cfm

$ git add _gmods/dsp_content_footer.cfm 
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#	modified:   _gmods/dsp_content_footer.cfm

$ git commit -m "Updated Content Footer"

After we commit the file, we need to Push the file to the Bit Bucket Remote Depo... and now once this is complete, Production and Bit Bucket Remote Repo are Version 2.1 and Dev is 3

$ git push
Counting objects: 7, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 569 bytes, done.
Total 4 (delta 3), reused 0 (delta 0)
   c600e77..07a5ac1  master -> master

Now, this is where the code clash could happen. Dev has gone from Version 2 to Version 3 directly, while Production went from 2 to 2.1... so Dev never got the .1 update. So now, we need to Pull the .1 update from the Git Remote Repo on Bit Bucket. 

Remember, Git is smart, so instead of overwriting Dev with Productions changes (like FTP would if you were working with older tools), Git will see that there is a file conflict, and try and resolve it... lets look at how that works.

$ git pull
remote: Counting objects: 7, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 4 (delta 3), reused 0 (delta 0)
Unpacking objects: 100% (4/4), done.
   c600e77..07a5ac1  master     -> origin/master
Merge made by recursive.

So we perform a git pull (we do not state the location, as we only have 1 remote, and 1 branch, so git instantly knows what to pull... if you have multiple remotes and or branches, you would need to be more specific)... and all looks good, but wait, that final line... what does it say?

Merge made by recursive.

That means Git noticed that there was a possible conflict, but it was one that it could figure out automatically. If this was not the case, a code clash would have temporarily corrupted that file by making it into a DIFF file, and having a copy of both files in the one file. The conflict would not have been as damaging though, because we had the merge on the Dev side, and it could be quickly resolved, and no live customers / clients / visitors never saw a problem on production.

So now, we have the following status of our repos.

  • Bit Bucket Repo - Version 2.1
  • Production Server - Version 2.1
  • Dev Server - Version 3.0 (including the .1 update)

So now we have merged our sets of changes, now we are finally ready to Push from Dev to Remote, and then Pull from Production, like we said initially. This practice of checking Production first doesn't apply for all situations, but because of our CMS and how we want to include Website Resources in our Repos, we have to follow these preliminary steps before pushing from Dev to Production.

Ok, so now, lets make sure our changes have been tracked, staged, and committed (not shown in this case - view other entries for how to track stage and commit changed)... then we can do our Git Push.

$ git push
Counting objects: 16, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (8/8), done.
Writing objects: 100% (9/9), 896 bytes, done.
Total 9 (delta 5), reused 0 (delta 0)
   07a5ac1..ac30df9  master -> master

Now, our Repos look like this.

  • Bit Bucket Repo - Version 3.0 including 2.1 update
  • Production Server - Version 2.1
  • Dev Server - Version 3.0 including 2.1 update

Now, the Dev server is merged and up to date, and so is our Bit Bucket Repo, so we can just pull the changed on Production from the Remote Bit Bucket Repo.

$ git pull
remote: Counting objects: 16, done.
remote: Compressing objects: 100% (8/8), done.
remote: Total 9 (delta 5), reused 0 (delta 0)
Unpacking objects: 100% (9/9), done.
   07a5ac1..ac30df9  master     -> origin/master
Updating 07a5ac1..ac30df9
 _gmods/pdfs/.gitignore  |    5 +++++
 errors/dumps/.gitignore |    6 ++++++
 2 files changed, 11 insertions(+), 0 deletions(-)
 create mode 100644 _gmods/pdfs/.gitignore
 create mode 100644 errors/dumps/.gitignore

The git pull was successful... and you can see what the pull did. Obviously in this case, my Version 3 upgrade was a couple of gitignore files. Good timing, as those are coming up soon in the Git for Dummies series, as we start to use Git more, we want to customize git options, so we know what files we want to track, what files we do not want to track, and learn a few more tricks out of the very cool and powerful Git Magic Trick bag.

Check back soon... thanks for reading.


Blog Search