Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
371 views
in Technique[技术] by (71.8m points)

Git: How to create patches for a merge?

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

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...