3

Is there a way to squash commits that have a merge commit? I am able to squash when there is not any merge commits but I don't know how to do it when there is one.

Like these two commits.

git tree

Burak Akyalçın
  • 302
  • 5
  • 26
  • How are you squashing? – tymtam Dec 15 '20 at 11:19
  • Why are we merging master into a feature branch? If the goal is to acquire the other merged fixes, why not rebase? Now there is no merge and you can squash. – matt Dec 15 '20 at 11:34
  • @matt so, instead of merging I should rebase and then squash, am I right? – Burak Akyalçın Dec 15 '20 at 11:56
  • I don't know about "should". I just don't understand why merge, if the goal is to erase the merge commit. – matt Dec 15 '20 at 12:03
  • Can you describe what you intend by "squash" in your case ? perhaps draw the final graph you would like to see ? – LeGEC Dec 15 '20 at 15:09
  • @LeGEC I just want these two commits to be a single commit – Burak Akyalçın Dec 15 '20 at 15:31
  • Here's a good answer: https://stackoverflow.com/a/32842174/341994 Tells you how to convert the merge commit to a normal commit (as if you had originally done a `merge --squash`), and then you can squash further with interactive rebase or soft reset. But you will lose the "merge" history; you cannot squash a merge commit, the idea doesn't really make sense. – matt Dec 15 '20 at 17:52
  • Ok, and do you still have a merge commit from master ? or a commit separated from master ? – LeGEC Dec 15 '20 at 18:24

1 Answers1

4

Here I've built a graph like yours before the merge:

* bbcdb99 (HEAD -> feature) d
| * d568728 (master) c
| * 8714c7f b
|/  
* f1aeb9a a

Now I merge master into feature:

*   264fc6c (HEAD -> feature) Merge branch 'master' into feature
|\  
| * d568728 (master) c
| * 8714c7f b
* | bbcdb99 d
|/  
* f1aeb9a a

Well, if I want to squash feature down to just one commit and erase the merge commit, then I should not have merged like that. I should have done a squash merge! However, all is not lost. I can just reset soft back to f1aeb9a and make a new commit:

$ git reset --soft f1aeb9a
$ git commit -m"new commit"

That gives this:

* e26b588 (HEAD -> feature) new commit
| * d568728 (master) c
| * 8714c7f b
|/  
* f1aeb9a a

Now "new commit" contains everything that was done on feature including the results of the merge from master. But of course we have lost the merge commit.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • thank you!! that's what I was looking for. – Burak Akyalçın Dec 15 '20 at 18:37
  • 1
    Cool! To repeat, we could have gotten here somewhat more directly if the original `merge` had been a `merge squash`. Then you could have done your branch squash with interactive rebase if you wish. However, it's useful to know that `reset --soft` plus `commit` is a form of squashing. See my essay on regret: https://stackoverflow.com/questions/3528245/whats-the-difference-between-git-reset-mixed-soft-and-hard/59675191#59675191 This was regret type 1. – matt Dec 15 '20 at 19:17