3

I've read a LOT of questions on here and help documents, but I can't seem to find any solid, understandable documentation that explains addresses my needs.

I work on a team that's making a major code change. We forked a branch off of our 'master' branch. This branch is a shared working branch for this feature work which we'll call 'feature-branch'. From this secondary branch, we've all forked new branches for our personal work (e.g. 'feature-branch-rlh', 'feature-branch-abc', etc.)

Over the past couple of weeks, we've all committed some work to our branches and merged that work into 'feature-branch'. Also, 'feature-branch' has had some work merged into it from 'master'.

We want to take all of our work from the past two weeks within 'feature-branch' and squash all of the commits, merges and conflict fixes into one commit. However, we want to leave the two commits that were merged from 'master'. The command I start with for the squash is this (where n is the number of commits to include):

git rebase --rebase-merges -i HEAD~n

I am primarily familiar with git rebase without using the --rebase-merges flag, but since merge conflict resolutions seem to be ignored every time I squash, I am trying to include the merges in the squash. When I run the command, instead of seeing familiar output like this in the interactive file:

pick 11111111 Details
pick 22222222 Details
pick 33333333 Details
pick 44444444 Details
...

I now see code that looks like this:

reset onto
pick 11111111 
pick 22222222 
pick 33333333 
label branch-point-2
pick 44444444 
label Merge-Commit

# Branch origin-feature-branch
reset branch-point-2 
pick 55555555 
label branch-point
pick 66666666 
pick 77777777 
merge -C 88888888 Merge-Commit # Merge Commit
pick 99999999 
label origin-feature-branch-rlh

# Branch master
reset branch-point-2 
pick aaaaaaaa Commit I want to keep, but not squash
label feature-branch

pick bbbbbbbb 
merge -C cccccccc 
pick dddddddd 
...

This is a very simplified list of commits I see in the interactive file. Specifically, what I want to do is squash all of these commits into the first commit (11111111). This includes the merge commits (like 88888888 and cccccccc), that are marked with merge -C. However, commit aaaaaaaa has a reset command before it, and I do NOT want to squash it and I'm not sure what to do.

How can I do squash all of the applicable commits? I've tried to re-order my list, putting the reset... pick... label... code at the end of the file and not changing it to squash, however since I don't change the merge to a squash (and honestly, I don't know if I should or not), something seems to be broken. I keep getting merge conflicts again and again, which have been fixed in former merges.

My end goal is to squash all of this, except for a couple of commits. However, no matter what I try, the merge conflicts keep getting in the way which, again, have been fixed in former merges. What do I need to do to solve this problem?

RLH
  • 15,230
  • 22
  • 98
  • 182
  • 2
    re: repeating conflicts, `git rerere`? At the very least, possibly combined with `rerere-train.sh`, solves the problem of redoing the same conflict. See https://stackoverflow.com/a/49501436/20270 – Hasturkun Mar 10 '22 at 15:46
  • @Hasturkun I've not heard of that feature. Reading it now. Thank you. – RLH Mar 10 '22 at 16:08
  • The only reason to preserve the merge commits for when `master` was merged in would be to preserve the state representation at that time. Therefore, it wouldn't really make sense to squash all commits into only *one* commit **and** maintain the 2 `master` merges unless all of those commits were together, say, before, between, or after both `master` merges (which I doubt is the case). cont... – TTT Mar 10 '22 at 19:29
  • If you intend to keep the `master` merges, it would probably make more sense to squash your other commits into 3 commits: squash all commits before `master` merge 1, then do `master` merge 1, then squash all commits between the 2 `master` merges, then do `master` merge 2, then squash all commits after. In this way state at the time of the `master` merges is preserved. – TTT Mar 10 '22 at 19:29
  • 2
    BTW, I'm pretty sure my last comment is the answer to your question. If you preserve the state at each merge, then those merges would not have conflicts. – TTT Mar 10 '22 at 22:01
  • (better late than never) I think this would be a case for `git replace --graft ... ; git filter-repo --force`. Would you have a script to create a history that looks like your starting point ? – LeGEC Nov 15 '22 at 07:56

0 Answers0