Reputation: 451
I made a few commits to my branch and then merged it into master with a CR. I want all the commits to that branch to be squashed, so I tried git rebase -i HEAD~3
and squashed the two most recent commits into the third most recent commit.
This then modified my local files, producing some sort of hybrid between the current version of master, and master several commits before I merged the CR. Several blocks of code are now encased with
<<<<<<< HEAD
{code from before CR merge}
=======
{code from current version of master}
>>>>>>> Branch hash from 8 commits before the CR merge
Why does squashing the most recent two commits resurrect changes from 8 commits ago?
I also tried git reset HEAD~2 --soft
, but git log
didn't show any changes or indicate that those two commits had been squashed into the other one.
git log --graph --pretty=%h HEAD~3..HEAD
(after running git reset HEAD~2 --soft
) produces
* 9387a5c
|\
| * f7624c3
| * f68a001
| * d7729a5
|/
* 8a1d144
|\
| * dea1b19
| * 70d5197
| |\
| |/
|/|
* | a5fe680
* | 35b9417
* | 1f3f921
* | ea1d7e5
* | 11a7fb4
* | 021e8c5
* | 5b9db7a
/
* b2e4905
9387a5c
is from merging the CR. git rebase
does not let me squash that commit, only starting from f7624c3
. I tried to squash f7624c3
and f68a001
into d7729a5
since they were all commits to the same branch for the same feature.
Upvotes: 1
Views: 99
Reputation: 1328122
I see HEAD
is pointing to the merge commit (9387a5c
), which means: doing a git rebase -i HEAD~3
would not include said merge commit as something you can squash. By default, interactive rebase simply drops merge commits from the todo
list, unless you enable --rebase-merges
(default since Git 2.22, Q2 20219) (or --preserve-merges
in older Git). That is why you can only pick/squash from f7624c3
and onward, not from the merge commit.
When you do git rebase -i HEAD~3
in this scenario, Git sees commits from your feature branch that originated from an older point in the master history. It then tries to apply those patches again on the latest master changes, triggering conflicts that can look like "ancient" code reappearing.
And, as amphetamachine mentions in their comment, git rebase
is made more complex when a merge commit contains changes that are not purely in its parents, making it more than a simple fast-forward or no-op merge. So when you "replay" that merge during a rebase, Git may try to reapply a conflict resolution. That is also when you see "resurrected" changes that come from older commits.
Upvotes: 1