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.
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
.gitignorerules 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 firstname.lastname@example.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
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
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
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
$ 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.
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.
This git graft process uses some serious Git-fu. Big thanks to Charles on the Pixo dev team for helping create this process.