When I use git format-patch
, it doesn't seem to include merges. How can I perform a merge and then e-mail it to someone as a set of patches?
For example, let's say that I merge two branches and perform another commit on top of the merge:
git init echo "initial file" > test.txt git add test.txt git commit -m "Commit A" git checkout -b foo master echo "foo" > test.txt git commit -a -m "Commit B" git checkout -b bar master echo "bar" > test.txt git commit -a -m "Commit C" git merge foo echo "foobar" > test.txt git commit -a -m "Commit M" echo "2nd line" >> test.txt git commit -a -m "Commit D"
This creates the following tree:
B / \ A M - D \ / C
Now I try to checkout the initial commit and replay the above changes:
git checkout -b replay master git format-patch --stdout master..bar | git am -3
This produces a merge conflict. In this scenario, git format-patch master..bar
only produces 3 patches, omitting "Commit M". How do I deal with this?
-Geoffrey Lee
To create a Git patch file, you have to use the “git format-patch” command, specify the branch and the target directory where you want your patches to be stored.
Make a new branch starting from the revision just before the first changeset. In the new branch, merge each changeset of the issue, in order. Take a diff between the start of the new branch and the final result. (If you do issue-based branching, you'd get the above situation automatically).
To merge branches locally, use git checkout to switch to the branch you want to merge into. This branch is typically the main branch. Next, use git merge and specify the name of the other branch to bring into this branch. This example merges the jeff/feature1 branch into the main branch.
There does not seem to be a solution producing individual commits à la git format-patch
, but FWIW, you can format a patch containing the effective merge commit, suitable/compatible with git am
:
Apparently, the Git Reference guide provides the first hint:
git log -p show patch introduced at each commit
[...] That means for any commit you can get the patch that commit introduced to the project. You can either do this by running
git show [SHA]
with a specific commit SHA, or you can rungit log -p
, which tells Git to put the patch after each commit. [...]
Now, the manual page of git-log gives the second hint:
git log -p -m --first-parent
... Shows the history including change diffs, but only from the "main branch" perspective, skipping commits that come from merged branches, and showing full diffs of changes introduced by the merges. This makes sense only when following a strict policy of merging all topic branches when staying on a single integration branch.
Which in turn means in concrete steps:
# Perform the merge: git checkout master git merge feature ... resolve conflicts or whatever ... git commit # Format a patch: git log -p --reverse --binary --pretty=email --stat -m --first-parent origin/master..HEAD > feature.patch
And this can be applied as intended:
git am feature.patch
Again, this won't contain the individual commits, but it produces a git am
compatible patch out of a merge commit.
Of course, if you don't need a git am
compatible patch in the first place, then it's way simpler:
git diff origin/master > feature.patch
But I guess you already figured as much, and if you landed on this page here, you are actually searching for the workaround/solution I've described above. ;)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With