GitFlow, squashing and merging issues
Asked Answered
R

1

5

I'm using GitFlow in my git repository, so I have a master, develop and (temporary) release branch.

Workflow

  1. I create a new branch from develop (e.g. fix/fix-the-bug)
  2. I squash my fix into meaningful commits
  3. I merge my fix/fix-the-bug branch into develop
  4. Once I've got enough branches merged, I create a (temporary) release/x.y.z branch from develop
  5. I version-bump my scripts in the release/x.y.z branch and tag that commit
  6. When I want to merge release/x.y.z into master, I get merge conflicts. It seems like master does not understand that commits are already present in master
  7. release/x.y.z branch gets merged into develop
  8. I delete release/x.y.z

Few things to notice, not sure if they are all correct:

  • I squash my commits into one commit when merging into master
  • There should be a git tag on master indicating the version number, but not sure if that would work correctly if I squash the commits.

Question

I'm now wondering:

  • how I can fix my repo, since I don't think I should be getting those conflicts.
  • Any further advice on the workflow (e.g. in which part I could perform the squash best) would be welcome.
Rewrite answered 4/5, 2020 at 14:56 Comment(0)
L
8

I squash my commits into one commit when merging into master

It sounds like you're using git merge --squash when you merge to master. This is not standard gitflow practice; you would just do a normal merge.

The entire difference between a regular merge and a squash merge is that a squash merge does not record the relationship between the new commit on the branch you're merging into (i.e. master in this case) and the original commits on the source branch; that's why subsequent merges don't understand that the content on master already corresponds to a previous state of develop.

The "downside" to using a regular merge is that git's default output, when logging master for example, would include all the individaul commits instead of just a list of the release commits on master; but you can fix that by using the --first-parent option.

To put this into visuals, you start with a blank repo

o <--(master)

Without creating commits, you start the develop branch, and then a fix branch on which you do some work

o <--(master)(develop)
 \
  A <--(fix)

You merge to dev

o <--(master)
|
|- M <--(develop)
\ /
 A <--(fix)

You might do more fixes

o <--(master)
|
|- M - M2 <--(develop)
| / \ /
| |  B <--(fix2)
\ |
 A <--(fix)

Now if you squash merge to master, you'll get something like

o -------- AB <--(master)
|
|- M - M2 <--(develop)
| / \ /
| |  B <--(fix2)
\ |
 A <--(fix)

and AB contains all the changes that A and B introduced, but as far as git is concerned, that's coincidental; and once develop contains additonal changs, even the fact that the changes are "the same" will be lost, and conflicts (as you've experienced) result.

So instead you do a regular merge - just leave out the --squash option, assuming you were using squash merges in the first place:

o ------- AB <--(master)
|        /
|- M - M2 <--(develop)
| / \ /
| |  B <--(fix2)
\ |
 A <--(fix)

This is how git means for merges to work; now future merge attempts will "know" that M2 (and everything it entails) is already included in master and only changes after M2 will be included as "their changs" in the merge calculation.

This also is how gitflow intends things to be done.

Ligialignaloes answered 4/5, 2020 at 15:18 Comment(7)
Thank you Mark for your extensive answer. So, if I understand correctly: 1) master will also contain the complete history as present in develop, but should be viewed with the --first-parent option? 2) I should leave the git-tag with the version number on the "version-bump" commit?Rewrite
@Rewrite - Your 1st quesiton assumes a relationship between branches and commits that doesn't exist in git; branches do not contain commits. A branch points to a commit, and what git displays as branch history is based on what commits are reachable from the branch (i.e. what commit it points to, and what commits can be found by recursively following parent pointers). AB's 2nd parent pointer makes the complete history reachable, meaning (1) the default log output (if you don't use --first-parent) shows it, and (2) AB is used as the merge base for the next merge of develop into masterLigialignaloes
@Rewrite - I don't understand the 2nd question.Ligialignaloes
Think I got the first one right now. About the second: I'm using this, which will tag the version-bump commit. So when I merged that into the master branch, I don't see the tag anymore (since it's not on the --first-parent). So I think I should I move the git tag to the merge commit on master, as mentioned on the GitFlow docs? $ git checkout master $ git merge --no-ff release/x.y.z $ git tag -a x.y.zRewrite
Thanks Mark, your replies have been very helpful in achieving the preferred workflow =)Rewrite
@Rewrite How did you initially fix your master branch so that you can continue working in the way Mark described? Also running into the same issue re. merges. I understand what I've done wrong and what the workflow should be, just not sure how to fix master to then follow the described workflowHerewith
@ftahir SInce this is about half a year ago, I'm not 100% sure. I think I just continued the suggested way and left the previous commits as-is, since I just started building releases when this issue occurred. So the first 3 releases or so are just one commit.Rewrite

© 2022 - 2024 — McMap. All rights reserved.