简体   繁体   中英

Git rebase merge on top of new upstream

I've finished complicated merge. During merge time upstream slightly / insignificantly moved forward.

Additionally I put extra private work before merging:

*   XXX (HEAD -> master) Merge 'feature' into 'master'.
|\
| * XXX (feature, origin/feature) Implementation of a feature.
* | XXX (private) Private progress on master.
| | * XXX (origin/master) New progress on master.
| |/
|/|
* | XXX (split) Point of split

Instead of merging master with origin/master I want to rebase private change + master merge on top of upstream origin/master :

*   XXX (HEAD -> master) Merge 'feature' into 'master'.
|\
| * XXX (feature, origin/feature) Implementation of a feature.
* | XXX (private) Private progress on master.
* | XXX (origin/master) New progress on master.
* | XXX (split) Point of split

The merge pointed by master was tough and the prior private change was served to simplify merge (like file renames to avoid conflicts).

origin/master doesn't have anything conflicting with my merge.

How can I rebase merge preserving all efforts I made during the merge?

Cherry pick private progress?

git checkout master
git branch temp
git reset --hard origin/master
git cherry-pick <private-progress-hash>
git merge feature --no-ff

temp is just in case something goes wrong.

I am in process of experimenting with the option --rebase-merges but documentation sates:

Any resolved merge conflicts or manual amendments in these merge commits will have to be resolved/re-applied manually.

As I have very troubling merge it is must simpler just to merge my merge to upstream than trying to rebase my merge on top of the upstream.

It looks like Git merging strategies during rebase cannot reuse human guided conflict resolutions...

UPDATE @eftshift0 gave interesting suggestion.

There is a problem with rerere . It is a database of conflict resolutions. You have to fill that database:

  • Running the git rerere command immediately after a conflicted automerge records the conflicted working tree files

  • Later, after you are done resolving the conflicts, running git rerere again will record the resolved state of these files.

I've already merged so I missed first step...

Still managed to recreate conflict using previous resolution and with updated rerere database:

# just start from new branch to preserve entire original history
$ git checkout -b private-new private
$ git merge feature
# got conflicts, remember them!
$ git rerere
Recorded preimage for 'README.md'
# repeat conflict resolution from existing merge commit using pathspec
$ git checkout master -- README.md
# update conflict resolution database
$ git rerere
Recorded resolution for 'README.md'.
# Finish merge (and now Git remember how to resolve conflicts!)
$ git merge --continue

Then rebase:

  • asking to preserve merge graph ( -r or --rebase-merges )
  • interactive ( -i ; you will see label , reset , merge extra language to verify or correct resulting rebase structure)
  • applying merge database ( --rerere-autoupdate ) for automatic conflict resolution from the recorded resolution history.
$ git rebase -i -r --rerere-autoupdate origin/master
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Staged 'README.md' using previous resolution.

As you see you still get conflicts but they are resolved from the database.

I've got exactly desired graph (except I used alternative private-new branch name). Exactly the same I asked in the question.

NOTE rerere is not active by default and is a subject of GC so you might lose you database with the time passed...

NOTE 2 Seems after activation rerere is applied automatically, see What is git-rerere and how does it work?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM