<p>I actually keep all the craft system files gitignored. This way, all the assets are independent of the version of Craft and therefore of the updates. When it's time to run an update, I'll do it on dev first and then I'll run it in production knowing that it'll be fine.</p>

<p>So far I have not had a problem with this approach and it seems to me that it is a more elegant way of doing things. </p>

<p>Now, in my installations I keep separate databases, maintaining the structure the same across all environments. When I need to see the same data from production, in dev, I'll import it manually. I can't say that this side of things is the easiest to work with but since I've had to deal with small databases until now it hasn't been much trouble. I am beginning a new, larger project so... things may change soon. :P</p>

<p>Here's my usual gitignore file for Crafty projects.</p>

<pre><code># CMS related files
craft/app/*
craft/storage/*
public/content/*
craft/config/license.key

# OS or program files
.DS_store
.tmproj
Thumbs.db
.Spotlight-V100
.Trashes

# Grunt
node_modules
build

# Others
*.sass-cache
*.sublime-project
*.sublime-workspace
</code></pre>

<p>The folder <code>public/content</code> is where all the assets generated by craft go. These get ignored since the real data is in storage.</p>

<p>As you can see, storage is ignored here, as I said before, that's because I keep separate databases. That works for me but it's certainly not ideal for larger environments.</p>

CC BY-SA 3.0
2017-04-30T21:57:04.047Z
The problem I have with this is if you have multiple developers on your team, then having one of them download the repo does not give them all the files they need, they still need to obtain Craft files from somewhere else, and it creates extra steps. The team would need a clear process on how to handle this without creating additional issues.
Simon East
CC BY-SA 3.0
2014-06-12T02:20:24.900Z
2014-06-12T02:20:24.900Z
cballenar
<p>I personally use a slightly different method than what Jeremy recommends.</p>

<ol>
<li>Clean repo on the git side of things: no unstaged or non committed files</li>
<li>Backup live DB and import in dev</li>
<li>Update dev (test)</li>
<li>Update production</li>
<li>Commit &amp; deploy</li>
</ol>

<p>Not encountered any problem so far and Craft runs its tests on both environments.</p>

CC BY-SA 3.0
2014-06-23T12:54:30.543Z
This is what I've tested as well, and it works for me.
Jon Horton
CC BY-SA 3.0
2014-06-12T03:58:30.607Z
2014-06-12T03:58:30.607Z
Jérôme Coupé
<p>I know your method works flawlessly, but it scares the crap out of me.</p>

<p>Luckily Craft's update setup is magical.</p>

<p>What I do is this.</p>

<ol>
<li><p>Make sure my repo is clear of unstaged files, just so the update can be in a commit all by itself.</p></li>
<li><p>Run the update on my local dev environment (with a local database) (Test)</p></li>
<li><p>Commit the updated files and push</p></li>
<li><p>Backup live database just in case</p></li>
<li><p>Deploy the files on live. (I use Beanstalk, so it uploads the files for me, but you can also do a git pull if that's your method of deployment.) Craft detects that the database version doesn't match the files and puts up a maintenance message.</p></li>
<li><p>Visit /admin and click the update button</p></li>
<li><p>Drink.</p></li>
</ol>

CC BY-SA 3.0
2014-06-12T01:12:49.613Z
So basically the reverse, with an intriguing last step! I appreciate the answer and am curious about how most people go about this.
Matt Stein
CC BY-SA 3.0
2014-06-12T02:09:57.820Z
This is basically how I do it as well. I'm a big fan of Step 1... Commit all of the updated "/app" files as their own isolated commit.
Lindsey D
CC BY-SA 3.0
2014-06-12T02:29:26.840Z
I like this route in that it gives you a chance to test the update locally first. Also, there could be a step 0 to this in that you could download the DB from production and update your local dev DB first. That way you're actual local testing is as close to production as possible.
Natetronn
CC BY-SA 3.0
2014-06-12T02:41:09.397Z
I approve of this answer, especially step #7.
Brad Bell
CC BY-SA 3.0
2014-06-12T09:30:46.520Z
Pretty much how I do it - Brandon recommended this way himself in one of the G+ threads. So far this has worked flawlessly.
erwinheiser
CC BY-SA 3.0
2014-06-15T16:00:42.230Z
For a single version upgrade, this method is smooth, but remember, the more files you deploy, each file deployed gets sent to your server one by one.  For larger updates, it's good to consider testing your upgrade like in step #2, and if all goes well, update step #5 to be 'Run the update in your production environment'.  If you run the one-click update in production, Craft downloads all the files as a zip and unpacks them on your server which is much quicker and reduces the chance for your site throwing temporary, odd errors while files make it to the server.
Ben Parizek
CC BY-SA 3.0
2014-06-15T17:59:27.150Z
Good point. Beanstalk deploys quite quickly, but yes, for a bigger update it could have some errors while the files are uploading. I would suggest temporarily renaming and replacing index.php with a maintenance message if this is the case.
Jeremy Gimbel
CC BY-SA 3.0
2015-05-05T17:43:24.847Z
so, what should you do if you want to eat? :)
polyclick
CC BY-SA 3.0
2015-08-13T23:20:34.060Z
I just followed these steps myself, and they worked great, thanks.
Stephen
CC BY-SA 3.0
2014-06-12T01:09:47.673Z
2014-06-12T01:09:47.673Z
Jeremy Gimbel
<p>It's thrilling to click The Button and watch Craft update itself. I take advantage of multi-site configurations with every deploy, and my practice thus far is to...</p>

<ol>
<li>Upgrade Craft in production.</li>
<li>Commit production file system changes via git.</li>
<li>Choose Settings → Backup Database and download the backup file.</li>
<li>Load the remote changes to my local environment via git.</li>
<li>Clear out and locally import the .sql backup I downloaded in step #3.</li>
</ol>

<p>I specifically update in production because I like thrills, and because I had previously done the opposite (upgrade locally, push live) and ran into problems.</p>

<p>This has been working for me pretty reliably and Craft upgrades always go smoothly, but I doubt that system updates on the production server are the <em>best</em> idea.</p>

<p>Is there a better way?</p>

<environments><upgrades><database>
What's the best practice for upgrading a versioned Craft site?
# What's the best practice for upgrading a versioned Craft site?

(Asked by: username_0 on 2014-06-12)

It's thrilling to click The Button and watch Craft update itself. I take advantage of multi-site configurations with every deploy, and my practice thus far is to...

1. Upgrade Craft in production.
2. Commit production file system changes via git.
3. Choose Settings → Backup Database and download the backup file.
4. Load the remote changes to my local environment via git.
5. Clear out and locally import the .sql backup I downloaded in step #3.

I specifically update in production because I like thrills, and because I had previously done the opposite (upgrade locally, push live) and ran into problems.

This has been working for me pretty reliably and Craft upgrades always go smoothly, but I doubt that system updates on the production server are the *best* idea.

Is there a better way?

**Tags:** environments, upgrades, database


---

## 3 answers

### Answer by username_5 on 2014-06-12. Score: 55 | Accepted answer

I know your method works flawlessly, but it scares the crap out of me.

Luckily Craft's update setup is magical.

What I do is this.

1. Make sure my repo is clear of unstaged files, just so the update can be in a commit all by itself.
2. Run the update on my local dev environment (with a local database) (Test)
3. Commit the updated files and push
4. Backup live database just in case
5. Deploy the files on live. (I use Beanstalk, so it uploads the files for me, but you can also do a git pull if that's your method of deployment.) Craft detects that the database version doesn't match the files and puts up a maintenance message.
6. Visit /admin and click the update button
7. Drink.

> **Comments:**
> **username_0**: So basically the reverse, with an intriguing last step! I appreciate the answer and am curious about how most people go about this.  
> **username_6**: This is basically how I do it as well. I'm a big fan of Step 1... Commit all of the updated "/app" files as their own isolated commit.  
> **username_7**: I like this route in that it gives you a chance to test the update locally first. Also, there could be a step 0 to this in that you could download the DB from production and update your local dev DB first. That way you're actual local testing is as close to production as possible.  
> **username_8**: I approve of this answer, especially step #7.  
> **username_9**: Pretty much how I do it - Brandon recommended this way himself in one of the G+ threads. So far this has worked flawlessly.  
> **username_10**: For a single version upgrade, this method is smooth, but remember, the more files you deploy, each file deployed gets sent to your server one by one.  For larger updates, it's good to consider testing your upgrade like in step #2, and if all goes well, update step #5 to be 'Run the update in your production environment'.  If you run the one-click update in production, Craft downloads all the files as a zip and unpacks them on your server which is much quicker and reduces the chance for your site throwing temporary, odd errors while files make it to the server.  
> **username_5**: Good point. Beanstalk deploys quite quickly, but yes, for a bigger update it could have some errors while the files are uploading. I would suggest temporarily renaming and replacing index.php with a maintenance message if this is the case.  
> **username_11**: so, what should you do if you want to eat? :)  
> **username_12**: I just followed these steps myself, and they worked great, thanks.  

---

### Answer by username_1 on 2014-06-12. Score: 15

I actually keep all the craft system files gitignored. This way, all the assets are independent of the version of Craft and therefore of the updates. When it's time to run an update, I'll do it on dev first and then I'll run it in production knowing that it'll be fine.
So far I have not had a problem with this approach and it seems to me that it is a more elegant way of doing things. 
Now, in my installations I keep separate databases, maintaining the structure the same across all environments. When I need to see the same data from production, in dev, I'll import it manually. I can't say that this side of things is the easiest to work with but since I've had to deal with small databases until now it hasn't been much trouble. I am beginning a new, larger project so... things may change soon. :P
Here's my usual gitignore file for Crafty projects.
# CMS related files
craft/app/*
craft/storage/*
public/content/*
craft/config/license.key

# OS or program files
.DS_store
.tmproj
Thumbs.db
.Spotlight-V100
.Trashes

# Grunt
node_modules
build

# Others
*.sass-cache
*.sublime-project
*.sublime-workspace

The folder public/content is where all the assets generated by craft go. These get ignored since the real data is in storage.
As you can see, storage is ignored here, as I said before, that's because I keep separate databases. That works for me but it's certainly not ideal for larger environments.

> **Comments:**
> **username_2**: The problem I have with this is if you have multiple developers on your team, then having one of them download the repo does not give them all the files they need, they still need to obtain Craft files from somewhere else, and it creates extra steps. The team would need a clear process on how to handle this without creating additional issues.  

---

### Answer by username_3 on 2014-06-12. Score: 11

I personally use a slightly different method than what Jeremy recommends.

1. Clean repo on the git side of things: no unstaged or non committed files
2. Backup live DB and import in dev
3. Update dev (test)
4. Update production
5. Commit & deploy

Not encountered any problem so far and Craft runs its tests on both environments.

> **Comments:**
> **username_4**: This is what I've tested as well, and it works for me.  

---

