Skip to content

Instantly share code, notes, and snippets.

@commonquail
Created October 14, 2017 07:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save commonquail/4cf64f17431939cffcede1a9db97697e to your computer and use it in GitHub Desktop.
Save commonquail/4cf64f17431939cffcede1a9db97697e to your computer and use it in GitHub Desktop.
Patch Git repo with diff between non-repo

Given two directories, one a Git repository and the other not, how do you apply the recursive diff between those two directories as a patch to the Git repository?

This might happen if you download source code without its history and make changes to it, then later acquire the history and wanting to secure your changes.

The easy way ...

... is to convert the non-repository into a Git repository before introducing the change. The change can then be turned into a patch with git format-patch [--binary] and applied with git apply or git am.

If you didn't think to do this it gets considerably more tricky.

The hard way ...

... requires creating a recursive patch with something like diff and applying it with patch or, preferably, git apply. In many situations this actually isn't difficult at all, it's just that there are a few edge-cases to look out for:

  • You have to tell diff to produce the unified diff format that git apply needs.
  • If your changes span subdirectories you have to tell diff to operate recursively.
  • If you do operate recursively you have to tell diff to ignore the .git folder in the destination repository to avoid corrupting it.
  • If you created any new files you need to explicitly tell diff to include them.
  • If there are any binary files you'll have trouble: diff only works with text, and the typical recommendation for binary diffs, bzdiff, doesn't solve any other problem diff solves. The safe approach is to resolve these manually but for platform independent binary files, such as images and PDFs, you can probably get away with instructing diff to treat them as text files; I've tried this successfully but I don't guarantee the result.
  • As with normal patch operation you need to strip a file name prefix when applying.

The final invocation, executed from within the destination repository, looks like this:

diff --exclude=.git --recursive --unified --new-file --text ../non-repo |
    git apply -p3

I can't remember if it's -p2 or -p3.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment