-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Merge Conflicts Resolving and Remembering them
Work in Progress as I try and work out how to do this (06-04-2019)..
When building a new release for Git-for-Windows, the full range of Windows patches the maintainer applies need to be moved (rebase
d) from being on top of the old upstream Git, to being on top of the new upstream release.
There is a process, a script and the support of the merging-rebase code, but still there maybe conflicts, old and new, especially if some of the Windows code has been adopted upstream in a different form.
This note looks at how to remember those resolutions, reuse them, and to learn from previous Git-for-Windows rebases. The magic is in the REuse REcorded REsolution (rerere) command and it's underlying database.
The documentation is terse, so let's also point to some on-line articles:
- Fun with rerere from the Git maintainer
- Fix conflicts only once with git rerere Nice graphs and examples.
-
Do you even rerere? Good discussion, including
rerere-train
. - rerere-train.sh use the 'blame' button for extra commit info.
- Are there any downsides to enabling git rerere? Not really, but read and learn.
- Smarter rebase avoiding redundant work? more rerere-train answers
- 7.9 Git Tools (book) - Rerere.
So, enable rerere
- git config --global rerere.enabled true
,
consider setting git config --global rerere.autoupdate true
and away you go!
Determine a previous Git-for-Windows merging-rebase end points and run the contrib/rerere-train.sh
Remember the parameters passed to rerere-train are <rev-list-args>
(apparently) for selecting the training set.
Threads about the internal workings:
- saving and replaying multiple variants with rerere 2015-09-14
- Should rerere auto-update a merge resolution? 2017-08-23
- rebase: use OPT_RERERE_AUTOUPDATE() 2019-03-19
- git/Documentation/technical/rerere.txt committed on 5 Aug 2018
- git rerere unresolve file 2009-11-21 patch series
- Make git-rerere a builtin 2006-12-20 convert from a perl script
- Add a test for git-rerere 2006-12-20
For the rerere (redo) database, it is worth taking a few moments to consider the difference between the conflict resolution that you would perform during a rebase when a patch fails to merge cleanly, and the conflict resolution for a merge.
For a subsequent rebase, of the repeating merging-rebase kind, it is easy to forget that the patches being forward ported to the new base commit already contain the previous resolution, so will not conflict next time, unless the upstream has changed, whereupon you have a new conflict to resolve.
This partially extends to the merges within the merging-rebase. If previous rebases have tidied the merging branches to avoid merge conflicts then there will be no resolutions to record. However if the cleanest approach was to resolve at merge, then the merge resolution can (should) be learned. Further, if you also had upstream changes and resolutions in the branches being merged, there may still be further residual merge resolutions to be performed. So unless the merges were clean then these are all new merge resolutions that should be learned (or relearned) for later reuse in redoing the next merging rebase.
Moreover, if you are rebasing a series that has temporary merges from upstream or other independent side merges (?Cousins?), then these resolutions will need to be remembered for future merging-rebase is repeated (after dropping those merges from the 'todo' list)
When upstream provides a tagged release, we create a commit with duplicated content tree (same oid hash) that has parents of: the upstream release and our previous release. This 'fake merge', with commit message title Start the merging-rebase
, along with its predecessor fake merge, provides anchors for the rebase of the patch series.
A side effect is that, via the second parent line, we have many repetitions of the same patch series when searching via blame
or grep
, or doing a git bisect
. The effect can be mitigated by inserting a temporary git replace
of the Start the merging-rebase
merge commit, by its first (upstream) parent, making the merge disappear, along with all those historical duplicate patches. It becomes: upstream Git, with Windows patches on top - simple.