1

For example, I just merged master branch to my feature branch. Then someone pushed new stuff on master. So I merged again to keep up. And then someone pushed again... I merge again. How do I squash the previous merges so that two merge actions is combined to one?

How can I turn this:

o---o---A---B---C---D---E
         \       \   \   \
          F---G---H---I---J

into this:

o---o---A---B---C---D---E
         \               \
          F---G-----------J'

where J and J' contain exactly the same codes.

flm8620
  • 1,411
  • 11
  • 15

2 Answers2

1

If you have only made merge commits to feature since G as in your diagram, you can reset your branch back to that commit (using --hard to also reset your working copy files), and then redo the merge:

git checkout feature
git reset --hard G
git merge master

You can also use git rebase master instead of git merge master so that your branch contains only commits F' and G', branching from E on master.

Adam Millerchip
  • 20,844
  • 5
  • 51
  • 74
  • 1
    Thanks. But in my case, I have resolved a lot of conflicts in "H" and "I", so I don't want to do it again. I really want some kind of squash that can reuse my conflict resolving. – flm8620 Oct 08 '18 at 07:49
1

This method prevents the need to re-resolve merge-conflicts by re-playing the previously-resolved changes into the merge commit.

git checkout feature
git diff master > feature.patch
git reset --hard G
git branch --move trimmed_feature
git checkout -b feature master
git merge --strategy ours trimmed_feature --no-edit
git apply feature.patch --index
git commit --amend --message "Merge branch 'master' into feature"
git branch -D trimmed_feature

We first remove the old merges to create a trimmed feature branch, then create a clean feature branch from master, merge in our trimmed feature branch using git merge --strategy ours to ignore the changes, then re-apply the previously-resolved changes from the patch.

Adam Millerchip
  • 20,844
  • 5
  • 51
  • 74
  • Thanks, I learned a lot about git today. But there is still a small problem, although the result of merge action in git is symmetric, a merged commit still distinguish its "first parent" and "second parent". The way you give inverted the two parents. I think the main difficulty comes from that git doesn't have "git merge --strategy theirs". – flm8620 Oct 08 '18 at 12:46
  • A previous version of this answer talked about "theirs" but I removed it for brevity. About the parent order, I don't think it has any practical effect on anything so I won't add it here, but if you really want to, [you can swap it](https://stackoverflow.com/a/36528357/1225617). – Adam Millerchip Oct 08 '18 at 13:04