Our Blog

Related Posts

Automating Plugin/Module Updates on Pantheon. We automated the process to apply plugin and module updates on Pantheon sites with a simple command.

Listen to Pixo and Four Kitchens' case studies on how we decoupled Drupal and Wordpress site architectures to separate CMS content from the front end.

Why We’re Decoupling Drupal by Brandon Bowersox-Johnson

The content-as-a-service approach, decoupling your CMS, is one that Pixo and others are adopting as a way to avoid the pain points of website development.

Popular Tags

Recent Comments

Cameron Macintosh

Everyone loves Pantheon hosting’s time-saving one-click updates for Drupal and WordPress. If you are putting a site onto Pantheon that already has revision history in Git, then you likely want to keep your history. But if you create a Pantheon site from an existing Git repo, one-click updates will not be available. Therein lies the need to graft both histories together.

Git Graft is a process in Git that allows you to rewrite history by “grafting” two histories together into one branch. Pantheon one-click updates only work when your codebase is rooted in Pantheon’s upstream Drupal or WordPress codebase (Drupal 6, Drupal 7, or WordPress). When there are security issues, the Pantheon team is quick to apply updates into their upstream, and then the one-click feature in your dashboard brings those updates into your master branch.

Overview

This Git Graft process applies to you if the following are true:

  • You are hosting a WordPress or Drupal site on Pantheon.
  • You have pre-Pantheon Git history for your site that you want to keep.
  • You want to use one-click updates to Drupal core or WordPress.
  • And of course you have not hacked core. Right?

Use the steps below to retain all of your Git revision history while also making Pantheon’s upstream the root of your Drupal or WordPress codebase, thereby making one-click updates available.  I’m assuming:

  • An Ubuntu/Linux environment
  • You have access to your current Git repo as well as a working Pantheon account.

Step 0: Laying the Groundwork

Since this process relies on git-merge behind the scenes, you will need to make sure your repository matches a vanilla install of Drupal or WordPress. Specifically,

  • WordPress: Install Akismet if you deleted it because your site does not support comments.  Also the default WordPress themes need to be present.  This link shows the theme currently in Pantheon’s upstream.
  • Move any custom .gitignore rules from the project root into applicable sub folders. This is mainly for Drupal, but this was the case for some of our WordPress sites as well.
  • If you have customized core in any way, you will likely need extra steps not covered here.
  • Make sure all active development has been merged back into your primary branch.

Also, if you wanted to retain a pristine backup of your master branch before the git graft rewrites history, you can create a branch for archiving purposes:

git checkout master
git checkout -b pre-graft
git push origin pre-graft

This would maintain a graft-free copy of your repository in case you needed to revert.

Finally, ask your other developers to check in and pause their work before doing this process. Because you are re-writing history, they will need to check out a fresh clone of the Git repo when you complete the Git Graft.

Step 1: Start With a Clone of Your Existing Repo

git clone git@bitbucket.org:ye-old-repo project-graft-start

First, make a fresh clone of your original project ye-old-repo.  I used the git-clone option to name the checkout directory project-graft-start to keep things clear and separate from my current/previous development work.

Note: Pantheon uses the master branch to deploy from dev through test to production, so make sure you graft from your project’s master branch, or whatever branch will become master.  Also make sure that master is current (if you’re starting from an existing checkout) or you will have to start this all over.

Due to the importance of the master branch to Pantheon, you may wish to create a new branch to perform your work on.  For the sake of these instructions, create a new branch graft-work from master:

cd project-graft-start
git checkout master
git checkout -b graft-work

Step 2: Fetch the Desired Pantheon Upstream

Pantheon uses different upstreams for the different content management systems they support: Drupal 6, Drupal 7, and WordPress.  Fetch the Pantheon upstream to a new branch called pantheon-upstream, making sure to use the appropriate pantheon upstream for Drupal 6/7 or WordPress:

# Drupal 6:
git fetch git://github.com/pantheon-systems/drops-6.git master:pantheon-upstream

# Drupal 7:
git fetch git://github.com/pantheon-systems/drops-7.git master:pantheon-upstream

# WordPress
git fetch git://github.com/pantheon-systems/WordPress.git master:pantheon-upstream

Step 3: Set Up the Graft

Much like grafting a real tree, to apply a git graft, you will need the two commits that will be linked together.  First, gather ye commit ID’s while ye may:

git rev-list graft-work | tail -n 1   # initial commit from ye-old-repo
git rev-parse pantheon-upstream       # latest pantheon-upstream commit

Then, record these commits in the grafts file (.git/info/grafts), putting the commit from your repository first, and both commits on the same line in the file separated by a space:

echo [ye-old-repo’s initial commit] [pantheon-upstream’s latest commit] > .git/info/grafts

Step 4: Apply the Graft

At this point, you have all the pieces, but they are not linked together.  To achieve this, first export the two and import them into the same repository:

git fast-export --all > ../graft-export
mkdir ../project-graft-complete
cd ../project-graft-complete/
git init
git fast-import < ../graft-export

Then check out the current files from pantheon-upstream to master in order to make sure they are up to date.

git checkout master
git checkout pantheon-upstream .

Originally, I tried using git merge -Xtheirs pantheon-upstream, but found that it does not work in this case.  I think that git already thinks the merge has happened.

Next, review the differences and perform any other cleanup you may need to do.  If you have customized core or have any custom .gitignore rules, you will need to take some care with this step.   Here is an example from a WordPress site after the checkout pantheon-upstream . step:

$ git status

# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
# modified:   .gitignore
# modified:   wp-content/mu-plugins/pantheon/pantheon-cache.php
# modified:   wp-content/mu-plugins/pantheon/pantheon-updates.php
# new file:   wp-content/plugins/hello.php
#

In the above case case, I needed to unstage the .gitignore file, move custom rules that were different from those provided by Pantheon into sub folders, and restage the files with git-add.  Then I was ready to commit these changes to complete the overlay.  Another file to watch out for is .htaccess.  We had a custom rewrite rule on a Drupal site that the pantheon upstream would have erased.

Caution: do not delete any of the plugins, themes, or modules present in pantheon’s upstream, otherwise you will likely run into conflicts that one-click updates won’t be able to resolve on its own.  These are required as part of Pantheon’s one-click updates.

Step 5: Push the Graft

The fast-export and fast-import steps above do not bring along the remotes.  In our case, we’re keeping our pre-Pantheon repo (named “origin” below) up-to-date with the project’s Pantheon repo.  Set up your remotes in the /project-graft-complete repository:

$ git remote add pantheon [url]
$ git remote add origin [url]

And push it!

git push pantheon master -f    # The main deploy branch on pantheon
git push pantheon --tags -f    # Some of your existing tags may
                               # be rejected.  This is ok.

git push origin master -f      # could git push --all, but that
                               # will push graft-work and
                               # pantheon-upstream branches too

git push origin --tags -f

At this point, only the master branch has been updated.  If you follow git flow or some variant, you can alternatively git push origin --all -f to update all your original branches.  Otherwise, just push the branches that are important to you.  Additionally, don’t forget to force push your tags back to origin.

**Now everyone who has a clone of this repo needs to re-clone the repo.**  Otherwise, pushing from an un-grafted clone of this repository can undo the graft.

Step 6: Your First Update

If everything worked, next time Drupal or WordPress has an update, you will see the one-click update available in your Pantheon dashboard. If the one-click updates fail the first time after applying the graft, you will need to do a git merge -Xtheirs pantheon-upstream locally to see the merge conflicts and resolve them manually.  (See this Pantheon article for more details.)

I encountered this issue during an early attempt at this process because I had deleted Akismet from a WordPress site that didn’t support comments.  When a new update became available, Pantheon’s dashboard reported unresolvable merge conflicts.  In my case, the solution amounted to re-installing Akismet before attempting the updates again.  Voilà!  Merge conflicts averted.  You could probably expect similar or worse if you have customized the WordPress or Drupal core.

Final Thoughts

Please let us know if you have any suggestions to improve this process. We learned all this the hard way, and we hope this post allows more people to benefit from the time-saving Pantheon one-click updates without losing their Git revision history. We also hope it helps preserve your Git history so you can use the ever-important git blame command.

Credits

This git graft process uses some serious Git-fu. Big thanks to Charles on the Pixo dev team for helping create this process.

Comments

2 thoughts on “Using Git Graft to Allow Pantheon One-Click Updates

  1. What a great tutorial! Unfortunately, the first line in step 4 returned an error:
    fatal: Tag 971e65e10ac1a7f5246510329037cb9a51558fbb tags unexported object; use --tag-of-filtered-object= to handle it.

    How can I get past this problem?

    Reply

Leave a reply

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> 

required

Related Posts

Automating Plugin/Module Updates on Pantheon. We automated the process to apply plugin and module updates on Pantheon sites with a simple command.

Listen to Pixo and Four Kitchens' case studies on how we decoupled Drupal and Wordpress site architectures to separate CMS content from the front end.

Why We’re Decoupling Drupal by Brandon Bowersox-Johnson

The content-as-a-service approach, decoupling your CMS, is one that Pixo and others are adopting as a way to avoid the pain points of website development.

Interested in working with us?
CONTACT US