I've got eight commits on a branch that I'd like to email to some people who aren't git enlightened, yet. So far, everything I do either gives me 8 patch files, or starts giving me patch files for every commit in the branch's history, since the beginning of time. I used git rebase --interactive to squash the commits, but now everything I try gives me zillions of patches from the beginning of time. What am I doing wrong?
git format-patch master HEAD # yields zillions of patches, even though there's
# only one commit since master
I'd recommend doing this on a throwaway branch as follows. If your commits are in the "newlines" branch and you have switched back to your "master" branch already, this should do the trick:
[adam@mbp2600 example (master)]$ git checkout -b tmpsquash
Switched to a new branch "tmpsquash"
[adam@mbp2600 example (tmpsquash)]$ git merge --squash newlines
Updating 4d2de39..b6768b2
Fast forward
Squash commit -- not updating HEAD
test.txt | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
[adam@mbp2600 example (tmpsquash)]$ git commit -a -m "My squashed commits"
[tmpsquash]: created 75b0a89: "My squashed commits"
1 files changed, 2 insertions(+), 0 deletions(-)
[adam@mbp2600 example (tmpsquash)]$ git format-patch master
0001-My-squashed-commits.patch
Hope this helps!
Just to add one more solution to the pot: If you use this instead:
git format-patch master --stdout > my_new_patch.diff
Then it will still be 8 patches... but they'll all be in a single patchfile and will apply as one with:
git am < my_new_patch.diff
I always use git diff so in your example, something like
git diff master > patch.txt
This is an adaptation of Adam Alexander answer, in case your changes are in master branch. This do the following:
- Creates a new throwaway branch "tmpsquash" from the point we want (look for the SHA key running "git --log" or with gitg. Select the commit you want to be tmpsquash head, the commits that are after that in master will be the squashed commits).
- Merges the changes from master to tmpsquash.
- Commits the squashed changes to tmpsquash.
- Creates the patch with the squashed commits.
- Goes back to master branch
laura@rune:~/example (master)$ git branch tmpsquash ba3c498878054e25afc5e22e207d62eb40ff1f38
laura@rune:~/example (master)$ git checkout tmpsquash
Switched to branch 'tmpsquash'
laura@rune:~/example (tmpsquash)$ git merge --squash master
Updating ba3c498..40386b8
Fast-forward
Squash commit -- not updating HEAD
[snip, changed files]
11 files changed, 212 insertions(+), 59 deletions(-)
laura@rune:~/example (tmpsquash)$ git commit -a -m "My squashed commits"
[test2 6127e5c] My squashed commits
11 files changed, 212 insertions(+), 59 deletions(-)
laura@rune:~/example (tmpsquash)$ git format-patch master
0001-My-squashed-commits.patch
laura@rune:~/example (tmpsquash)$ git checkout master
Switched to branch 'master'
laura@rune:~/example (master)$
As you already know, a git format-patch -8 HEAD
will give you eight patches.
If you want your 8 commits appear as one, and do not mind rewriting the history of your branch (o-o-X-A-B-C-D-E-F-G-H
), you could :
git rebase -i
// squash A, B, C, D, E ,F, G into H
or, and it would be a better solution, replay all your 8 commits from X
(the commit before your 8 commits) on a new branch
git branch delivery X
git checkout delivery
git merge --squash master
git format-patch HEAD
That way, you only have one commit on the "delivery" branch, and it represent all your last 8 commits
Format-patch between two tags:
git checkout <source-tag>
git checkout -b <tmpsquash>
git merge --squash <target-tag>
git commit -a -m "<message>"
git format-patch <source-tag>
Easiest way is to use git diff
, and add in git log
if you want the combined commit message that the squash method would output. For example, to create the patch between commit abcd
and 1234
:
git diff abcd..1234 > patch.diff
git log abcd..1234 > patchmsg.txt
Then when applying the patch:
git apply patch.diff
git add -A
git reset patch.diff patchmsg.txt
git commit -F patchmsg.txt
Don't forget the --binary
argument to git diff
when dealing with non-text files, e.g. images or videos.
Based on Adam Alexander's answer:
git checkout newlines
## must be rebased to master
git checkout -b temporary
# squash the commits
git rebase -i master
git format-patch master
来源:https://stackoverflow.com/questions/616556/how-do-you-squash-commits-into-one-patch-with-git-format-patch