Applying a patch that creates new directories

Applying a diff file using patch(1) fails in case that the diff file introduces new directories. This situation can happen, for example, when you work in a git repository as I do, commit a subdirectory with some files in it, then squash all your commits into a single commit using git rebase -i and finally create a diff file using git format-patch.

In my case, I had to apply my work done in a git repository on top of a subversion branch. During the development, I added tons of test fixtures in a fixtures/ directory. But when applying the final patch on top of the subversion branch, my test fixtures all ended up in the root directory, overwriting each other, as that’s what patch(1) does when it comes across a non-existing directory.

Solution

Assuming your diff file is called 0001-Your-Changes.patch, the following Ruby script will scan your diff file and create all neccessary directories:

ruby -n -E utf-8 -r fileutils \
  -e 'FileUtils.mkdir_p(File.dirname($1.split("/")[1..].join("/"))) if $_ =~ /^[+][+][+]\s(.*)$/' \
  < 0001-Your-Changes.patch

Then proceed by running patch -p1 < 0001-Your-Changes.patch as usual.

Check the -n command line option of ruby(1), which behaves similar to sed and awk.