Reputation: 434
These are the commit hashes in my branch. The PUSHED commits are part of the public master which was the base of my branch. The other commits are not yet pushed to public.
PUSHED_A - PUSHED_B - mywork_A - mywork_B - correction_A
Now I used git rebase -i
to reorder and squash correction_A into mywork_A.
I understand why mywork_A and mywork_B have a new commit hash after rebasing.
But now even PUSHED_B has got a new hash. The hashes now look like this
PUSHED_A - PUSHED_B2 - mywork_A2 - mywork_B2
I am afraid this will make it hard to correctly merge my branch into the public master branch because PUSHED_B2 is not recognized as the alread existing PUSHED_B and will cause problems.
I corrected that (new branch, cherry picking...) but I don't understand the backgrounds.
I looked at the commit content of both PUSHED_B and PUSHED_B2. There is no difference.
Perhaps I took PUSHED_B into the list of commits when doing the rebase, chosing HEAD~x too large. But I did not modify this commit and didn't reorder something before it. So even if it was part of the commits in the list, shouldn't it be left as it was?
Can I trace back what happened and when this happened?
Upvotes: 1
Views: 568
Reputation: 487705
Note that some forms of git rebase
attempt to notice that a particular existing commit can be reused, and will then re-use that existing commit (by "fast forwarding"). If you don't want that to happen, git rebase
offers options to disable it. Other forms of git rebase
are less careful about this: in effect, those options are always on. It seems likely you used the less-careful form of rebase.
The BEHAVIORAL DIFFERENCES section of the git rebase
documentation alludes to the three "back end" internal implementations: am (which uses git format-patch
and git am
to accomplish the copying, rather than cherry-picking commits), merge (which uses cherry-pick), and interactive (which uses cherry-pick but first generates an instruction sheet that you can edit, and gets pretty fancy):
git rebase
command switches to the merge back-end if you supply -m
, -s
, or -X
options.git rebase
command switches to the interactive back-end if you use -i
.In Git a year or so ago, rebase was mainly written as shell scripts and it was easier to tell which rebase did what. The new one is in C and much more opaque. The -p
option used to us the interactive back end, but not interactively, and maybe still does; the -r
or --rebase-merge
might also. It's clear that neither uses the old am back end, and, from the description in the documentation, that -k
cannot use the am back end either.
As kan said, you can re-rebase to put the two have-to-be-different commits back atop the original sequence of commits. Or, as you did, you can use git cherry-pick
manually, which gives you full control over every step, at the price of requiring full control over every step. :-)
Upvotes: 2
Reputation: 28951
When you rebase, it changes 'committer' and date of rebased commits, hence there is a new hash.
Simplest way is to rebase again against upstream using correct commit range. In this case git will detect that PUSHED_B and PUSHED_B2 has the same content, and will skip the latter.
Upvotes: 2