6

I have a develop branch with multiple commits. This branch shall be merged into the master branch. I also would like the master branches commit history to be as clean as possible, so I want to only have one entry for the merge. Thus I do the following:

git merge --squash develop
git commit

Now all changes from develop are in master, and there is only one commit on master. So far so good :-)

Now the problem is, that master and develop seem to be out of sync. I.e. if I make another commit to develop, I cannot merge that into master anymore. Lots of conflicts are popping up.

How exactly is the squash merge supposed to be done, so that both branches are in sync afterwards?

Boris
  • 8,551
  • 25
  • 67
  • 120

2 Answers2

5

1) The "typical" workflow your squash strategy is meant to avoid

# Initial situation

A---B---C <<< master
         \
          D---E---F <<< develop

# then the merge is done into master

A---B---C-----------G <<< master
         \         /
          D---E---F <<< develop

# no broken history but now master has three (probably noisy) commits


2) Your described (and unsatisfactory) workflow

# Initial situation

A---B---C <<< master
         \
          D---E---F <<< develop

# then you squash D, E and F into commit G on master

A---B---C---G <<< master
         \
          D---E---F <<< develop

# as you noticed, at this point master's history is "clean" but develop is out of sync


3) The alternative workflow I suggest to you

(git reset --soft <commit> is moving HEAD to point elsewhere but keeps your changes in the working tree, ready to be committed (or not)) (doc)

# Initial situation

A---B---C <<< master
         \
          D---E---F <<< develop

# squash your commits D, E and F on develop itself, THEN bring the new commit on master

git checkout develop
git reset --soft master
git commit -m "This is my message for these three commits"

A---B---C <<< master
         \
          G <<< develop

git checkout master
git merge develop

A---B---C---H <<< master
         \ /
          G <<< develop

# now histories are kept related but you have only one (properly remessaged and squashed) commit

Romain Valeri
  • 19,645
  • 3
  • 36
  • 61
  • Thanks for your suggestion. The problem I see with your suggested solution is that the commit history is now completely gone. The feature branch was deleted after merging it to develop, and on develop the commits were squashed. So in the end neither master nor develop nor the (deleted) feature branch have the full commit history. Since the feature branch should be deleted and master should not contain this detailed history, develop would be the only place to keep it. Thus squashing there seems not to be the right way. – Boris Jul 16 '20 at 11:23
  • @Boris Oh, I didn't get that you want to keep these commits. But then you're asking for short *and* long sticks, if you allow this corny analogy. If you do need these commits, why not doing a simple merge? What is the squashing for here? – Romain Valeri Jul 16 '20 at 11:38
  • In a git tutorial I read, it said that each commit on master should correspond to a realease (including tag and proper product versioning). Thus I thought, that develop is meant for active development and should keep track of the whole commit history. Master on the other hand is only updated once in a while with a single commit that includes all the changes from develop up until that point. Maybe I got that wrong? – Boris Jul 16 '20 at 11:44
3

My suggestion is to merge the master branch in the development branch after the merge --squash commit.

So the workflow looks like this:

git checkout master 
git merge --squash develop
git commit

git checkout develop
git merge master
learning2code
  • 460
  • 4
  • 9