Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Git: How to create patches for a merge?

Tags:

git

merge

patch

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

like image 456
geofflee Avatar asked Feb 18 '10 01:02

geofflee


People also ask

How do I create a patch in git?

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.

How do I merge patch files?

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).

How do I create a merge in git?

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.


1 Answers

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 run git 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. ;)

like image 119
sun Avatar answered Sep 18 '22 13:09

sun