git: generate a single patch across multiple commits
Solution 1
The following command creates a single .patch
file that contains multiple commits.
git format-patch cc1dde0dd^..6de6d4b06 --stdout > foo.patch
You can then apply it like so:
git am foo.patch
Note: Be sure to use ^..
instead of ..
if you want the first commit SHA to be included.
Solution 2
Create a new branch named squashed
that has a single squashed commit. This branch will have the exact same contents as your normal branch but none of the history.
Look it over and if you're satisfied, use format-patch
to create a patch file.
$ git checkout -b squashed $(git commit-tree HEAD^{tree} -m 'Squashed history')
$ git format-patch --root HEAD
This is a non-destructive operation and you can switch right back to your normal development branch afterwards. You can tag
the squashed branch to save a reference to what you e-mailed them, or use branch -D
to delete it if you no longer need it.
$ git branch -D squashed
Solution 3
You can use git diff
:
git diff 0f3063094850 > ./test.patch
SimpleCoder
Updated on March 17, 2021Comments
-
SimpleCoder over 3 years
This is the situation:
We created a "private" repo (say our-repo) based off an existing open-source git repo (say source-repo).
We have been developing code and have around 20 merges into our repo. So, the repo moved from "State_Initial" to "State_Current".
Now, for business reasons, we want to hand-over all our development to a third party. Based on some legal issues, the only option is we give them a "single" patch file with all our changes. That is a squashed patch between "State_Initial" and "State_Current".
I looked around, and found
git format-patch -X
But, it generates "n" .patch files.
Is there a way to create a single patch file, so that if we create a repo based off "source-repo" and apply the patch, it takes us to "State_Current"?
-
aleclarson over 5 yearsThat generates one
.patch
file per commit. The asker wants a single.patch
file that contains all commits in the given range. -
John Kugelman over 4 yearsWarning: This produces one file containing multiple separate patches. It doesn't squash the history down as requested in the question. If there are sensitive commits in the middle they'll be exposed.
-
GuyPaddock over 4 yearsHow do you specify the start of the commit range, though? It looks like this captures all of the files of the branch in a single commit, going back to the initial commit.
-
Priyanshu about 3 yearsIf you want to squash multiple commits into a patch then you can squash them by rebasing and then can make the squashed commit as a patch.
-
ThermoX about 3 yearsJust to clarify (maybe for Windows users only?). This command resulted in an error for me when doing the "git am foo.patch" part. I got a "Patch: format detection failed" error. What worked was to create the patch using the command: git format-patch cc1dde0dd^..6de6d4b06 --output=foo.patch
-
Jordan Bradford almost 3 years@ThermoX Were you using PowerShell? From my testing it seems that If you run the --stdout version of the command from PowerShell you'll get a UTF-16 LE BOM-encoded file with Windows line endings instead of a UTF-8–encoded file with UNIX line endings, and that's probably why the patch doesn't apply cleanly. So use Git Bash or cmd.exe for best results.
-
ThermoX almost 3 years@Jordan Bradford Yes, I was using PowerShell with the posh-git extension. I probably should have mentioned that in my original comment. Looking at the encoding, I am getting UTF-8 for the --output version, while as I am getting UCS-2 LE BOM for the --stdout. When running this under a cmd shell, you are correct. They both come out at UTF-8. However, I then need to use ^^ instead of ^. So I just keep using PowerShell and the --output version, which works fine. But glad to know the reason --stdout wasn't working there.
-
Addison Klinke over 2 yearsFor the curious, this is the official git docs for selecting ranges of commits based on
..
and^
syntax -
Addison Klinke over 2 yearsAs explained in this answer,
git format-patch
may be preferred overgit diff
since it includes metadata for the changes (i.e. committer identity, timestamps, commit messages, etc)