2

The basis of this question can be like at Finding a branch point with Git?

.-- X -- A -- B -- C -- D -- F  (master) 
.          \     /   \     /
.           \   /     \   /
.             G -- H -- I -- J  (branch A)

So I'm looking for a git diff which includes only commits of G+H+I+J

I'm afraid it is not possible to get it because branchA was merged back to master several times, and master was also merged in to branchA several times.

Community
  • 1
  • 1
dave.st
  • 21
  • 3

2 Answers2

1

git diff G J should give you G+H+I+J, but since you're concerned about merging, what you want is probably the diff for G+H+J — excluding merges. I'm afraid you'd need to create a temporary branch and cherry-pick these commits to get the diff you need.

Michael Krelin - hacker
  • 122,635
  • 21
  • 184
  • 169
  • Yes, you're right, I need H+J, I don't need G+I which are the merges. I hope there's another way, not only cherry-picking, as H+J are not only two commits but lot more... – dave.st Nov 14 '11 at 18:07
  • Maybe you can automate cherry-picking. I can't think of anything better. The problem is that cherry-picking may also come with conflicts and that's basically why I doubt a better way exists. – Michael Krelin - hacker Nov 14 '11 at 18:12
  • I couldn't create any good cherry-pick automation for this as I don't want to define commits one by one because of the number of the commits (around 100). – dave.st Nov 14 '11 at 18:19
  • Should be something like `git log A..J --oneline|grep -v Merge|cut -d\ -f1`, except for grep extension should probably be more elaborate. Best of all, of course, based on the number of ancestors. – Michael Krelin - hacker Nov 14 '11 at 18:26
  • @dave.st: `G` is not a merge commit in your diagram. – Cascabel Nov 14 '11 at 19:16
  • @Jefromi, indeed, thought it's more for me, than dave.st. – Michael Krelin - hacker Nov 14 '11 at 19:44
0

Unfortunately, without creating new commits somehow, this isn't really defined. It's possible that the diff introduced by J doesn't even make sense without what was merged in I, namely B and C.

Assuming that J really is disjoint from B and C, you do need to create new commits somehow in order to get the combined diff, because what you're asking for is impossible (in general) to determine without iteratively applying patches and seeing what the result is. The quickest way to do this, though, is not by cherry-picking. Instead you can take advantage of the fact that rebase by default does not preserve merge commits. Therefore:

# create a temporary copy of branch A
git branch branch-A-tmp branch-A
# rebase that copy in place, thus removing the merge commits
git rebase commit-A branch-A-tmp
# examine the diff
git diff commit-A branch-A-tmp

If the changes made in J are not separable from those in B and C, merged in I, you'll get merge conflicts when rebase attempts to re-apply J, thus indicating that the diff you're asking for is not well-defined. Otherwise, you'll get the diff you're looking for.

Cascabel
  • 422,485
  • 65
  • 357
  • 307