7

I need to keep a copy of WordPress in my project's Git repository.

I want to use Git to pull down WordPress updates from GitHub, and then push out those updates via git push and/or git svn dcommit.

I currently have a solution in place using Git submodules, and it works; but now I need to deploy my newest project to a server that only supports SVN, and to which I have no direct access whatsoever. Therefore, submodules are out.

I've done a ton of reading on Git's subtree merging strategy, and I think it's the right solution; but everything I've read expects that I'd want to follow a remote branch, and always pull down its most recent code.

On the contrary, WordPress on GitHub uses its master branch – in fact, all of its branches – for development; releases are tagged, but that's it. Officially speaking, all branches are in a perpetual alpha state.

I think what I need to figure out is how to subtree merge a tag.

Right now, I'm doing this to read WordPress 3.5 into webroot/wordpress (and to namespace WordPress tags), and it works:

$ git remote add -t master --no-tags wordpress git://github.com/WordPress/WordPress.git
$ git config --add remote.wordpress.fetch +refs/tags/*:refs/tags/wordpress/*
$ git fetch wordpress
warning: no common commits
remote: Counting objects: 138547, done.
remote: Compressing objects: 100% (28297/28297), done.
remote: Total 138547 (delta 110613), reused 137367 (delta 109624)
Receiving objects: 100% (138547/138547), 46.05 MiB | 2.26 MiB/s, done.
Resolving deltas: 100% (110613/110613), done.
From git://github.com/WordPress/WordPress
 * [new branch]      master     -> wordpress/master
 * [new tag]         1.5        -> wordpress/1.5
...
 * [new tag]         3.5        -> wordpress/3.5
 * [new tag]         3.5.1      -> wordpress/3.5.1
$ git read-tree --prefix=webroot/wordpress/ -u wordpress/3.5
$ git commit -m "Added WordPress 3.5 at webroot/wordpress"
[master c483104] Added WordPress 3.5 at webroot/wordpress
 1061 files changed, 269102 insertions(+)
 create mode 100644 webroot/wordpress/index.php
 create mode 100644 webroot/wordpress/license.txt
 create mode 100644 webroot/wordpress/readme.html
...

No matter what I try, though, I can't figure out how to use subtree merging to update this with WordPress 3.5.1.

Trying merge and read-tree, as per this, doesn't work:

$ git merge -s ours --squash --no-commit wordpress/3.5.1
Squash commit -- not updating HEAD
Automatic merge went well; stopped before committing as requested
$ git read-tree --prefix=webroot/wordpress/ -u wordpress/3.5.1
error: Entry 'webroot/wordpress/index.php' overlaps with 'webroot/wordpress/index.php'.  Cannot bind.

Trying a subtree merge fails:

$ git merge -s subtree --squash --no-commit wordpress/3.5.1
warning: Cannot merge binary files: webroot/wordpress/wp-includes/js/tinymce/wp-tinymce.js.gz (HEAD vs. wordpress/3.5.1)
...
Squash commit -- not updating HEAD
Automatic merge failed; fix conflicts and then commit the result.

(git pull -s subtree --squash --no-commit wordpress 3.5.1 fails the same way.)

I've tried adding -Xtheirs to git merge, I've tried a recursive merge with -Xsubtree, I've tried every combination of temporary branches and subtree merging that I can figure out – but I can't seem to crack this.

Any ideas? Or should I just give up and download (and re-download, and re-download) WordPress the old-fashioned way?

Aaron Adams
  • 1,657
  • 16
  • 23

1 Answers1

10

If all you want to do is frequently pull a remote's files into your project, and you don't care about connecting its history to yours, then no merging is required whatsoever.

Ultimately, the solution is dead simple:

  • Remove the old version of WordPress from the Git index;
  • Pull the new version of WordPress into the Git index with read-tree;
  • Commit.

read-tree is the only tool you need here, and since read-tree (smartly) refuses to overwrite files, you just need to remove the old tree from the index before reading the new one into its place.

$ git rm -r webroot/wordpress
rm 'webroot/wordpress/index.php'
rm 'webroot/wordpress/license.txt'
rm 'webroot/wordpress/readme.html'
...
$ git read-tree --prefix=webroot/wordpress/ -u wordpress/3.5.1
$ git commit -m "Updated to WordPress 3.5.1"
[master 9665ad7] Updated to WordPress 3.5.1
 44 files changed, 406 insertions(+), 176 deletions(-)
 rewrite webroot/wordpress/wp-admin/js/post.min.js (81%)
 rewrite webroot/wordpress/wp-includes/js/media-editor.min.js (99%)
 rewrite webroot/wordpress/wp-includes/js/media-views.min.js (89%)
...
Aaron Adams
  • 1,657
  • 16
  • 23
  • I gather `wordpress/3.5.1` is in gitignore? – jrhorn424 Sep 02 '13 at 18:23
  • Nope, I keep the WordPress files in my repo. In this specific case, it was because that's the only way to push them out via `git-svn`; in general, though, I do so regardless, because reliability and portability are far more important to me than, say, repo size. – Aaron Adams Sep 02 '13 at 21:39
  • I don't think I'm completely groking the use-case, then. Is `wordpress/3.5.1` a submodule or subtree? I thought the original problem [over here](http://stackoverflow.com/a/13756592/402618) was that subtrees are broken on remote deploy. Maybe you have a blog about this I haven't found? – jrhorn424 Sep 03 '13 at 14:37
  • 1
    @jrhorn424 No blog post yet, I do need to write that. The original problem was that _submodules_ were broken on remote deploy; subtrees are basically the method I'm recommending above. In the question, I go through the initial setup: add the repo, configure it to "namespace" tags ([like this](http://stackoverflow.com/a/5496610/802414)), fetch, `read-tree` the namespaced tag (`wordpress/3.5.1`) into my work tree, and commit. The answer details how I then update WordPress (or CodeIgniter, or Bootstrap, etc.) to new releases. I've been using this method for over 6 mos now and it works perfectly. – Aaron Adams Sep 03 '13 at 19:01