diff options
Diffstat (limited to 'Documentation/git-rerere.txt')
-rw-r--r-- | Documentation/git-rerere.txt | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/Documentation/git-rerere.txt b/Documentation/git-rerere.txt new file mode 100644 index 000000000000..4cfc88337808 --- /dev/null +++ b/Documentation/git-rerere.txt @@ -0,0 +1,222 @@ +git-rerere(1) +============= + +NAME +---- +git-rerere - Reuse recorded resolution of conflicted merges + +SYNOPSIS +-------- +[verse] +'git rerere' ['clear'|'forget' <pathspec>|'diff'|'remaining'|'status'|'gc'] + +DESCRIPTION +----------- + +In a workflow employing relatively long lived topic branches, +the developer sometimes needs to resolve the same conflicts over +and over again until the topic branches are done (either merged +to the "release" branch, or sent out and accepted upstream). + +This command assists the developer in this process by recording +conflicted automerge results and corresponding hand resolve results +on the initial manual merge, and applying previously recorded +hand resolutions to their corresponding automerge results. + +[NOTE] +You need to set the configuration variable `rerere.enabled` in order to +enable this command. + + +COMMANDS +-------- + +Normally, 'git rerere' is run without arguments or user-intervention. +However, it has several commands that allow it to interact with +its working state. + +'clear':: + +Reset the metadata used by rerere if a merge resolution is to be +aborted. Calling 'git am [--skip|--abort]' or 'git rebase [--skip|--abort]' +will automatically invoke this command. + +'forget' <pathspec>:: + +Reset the conflict resolutions which rerere has recorded for the current +conflict in <pathspec>. + +'diff':: + +Display diffs for the current state of the resolution. It is +useful for tracking what has changed while the user is resolving +conflicts. Additional arguments are passed directly to the system +'diff' command installed in PATH. + +'status':: + +Print paths with conflicts whose merge resolution rerere will record. + +'remaining':: + +Print paths with conflicts that have not been autoresolved by rerere. +This includes paths whose resolutions cannot be tracked by rerere, +such as conflicting submodules. + +'gc':: + +Prune records of conflicted merges that +occurred a long time ago. By default, unresolved conflicts older +than 15 days and resolved conflicts older than 60 +days are pruned. These defaults are controlled via the +`gc.rerereUnresolved` and `gc.rerereResolved` configuration +variables respectively. + + +DISCUSSION +---------- + +When your topic branch modifies an overlapping area that your +master branch (or upstream) touched since your topic branch +forked from it, you may want to test it with the latest master, +even before your topic branch is ready to be pushed upstream: + +------------ + o---*---o topic + / + o---o---o---*---o---o master +------------ + +For such a test, you need to merge master and topic somehow. +One way to do it is to pull master into the topic branch: + +------------ + $ git switch topic + $ git merge master + + o---*---o---+ topic + / / + o---o---o---*---o---o master +------------ + +The commits marked with `*` touch the same area in the same +file; you need to resolve the conflicts when creating the commit +marked with `+`. Then you can test the result to make sure your +work-in-progress still works with what is in the latest master. + +After this test merge, there are two ways to continue your work +on the topic. The easiest is to build on top of the test merge +commit `+`, and when your work in the topic branch is finally +ready, pull the topic branch into master, and/or ask the +upstream to pull from you. By that time, however, the master or +the upstream might have been advanced since the test merge `+`, +in which case the final commit graph would look like this: + +------------ + $ git switch topic + $ git merge master + $ ... work on both topic and master branches + $ git switch master + $ git merge topic + + o---*---o---+---o---o topic + / / \ + o---o---o---*---o---o---o---o---+ master +------------ + +When your topic branch is long-lived, however, your topic branch +would end up having many such "Merge from master" commits on it, +which would unnecessarily clutter the development history. +Readers of the Linux kernel mailing list may remember that Linus +complained about such too frequent test merges when a subsystem +maintainer asked to pull from a branch full of "useless merges". + +As an alternative, to keep the topic branch clean of test +merges, you could blow away the test merge, and keep building on +top of the tip before the test merge: + +------------ + $ git switch topic + $ git merge master + $ git reset --hard HEAD^ ;# rewind the test merge + $ ... work on both topic and master branches + $ git switch master + $ git merge topic + + o---*---o-------o---o topic + / \ + o---o---o---*---o---o---o---o---+ master +------------ + +This would leave only one merge commit when your topic branch is +finally ready and merged into the master branch. This merge +would require you to resolve the conflict, introduced by the +commits marked with `*`. However, this conflict is often the +same conflict you resolved when you created the test merge you +blew away. 'git rerere' helps you resolve this final +conflicted merge using the information from your earlier hand +resolve. + +Running the 'git rerere' command immediately after a conflicted +automerge records the conflicted working tree files, with the +usual conflict markers `<<<<<<<`, `=======`, and `>>>>>>>` in +them. Later, after you are done resolving the conflicts, +running 'git rerere' again will record the resolved state of these +files. Suppose you did this when you created the test merge of +master into the topic branch. + +Next time, after seeing the same conflicted automerge, +running 'git rerere' will perform a three-way merge between the +earlier conflicted automerge, the earlier manual resolution, and +the current conflicted automerge. +If this three-way merge resolves cleanly, the result is written +out to your working tree file, so you do not have to manually +resolve it. Note that 'git rerere' leaves the index file alone, +so you still need to do the final sanity checks with `git diff` +(or `git diff -c`) and 'git add' when you are satisfied. + +As a convenience measure, 'git merge' automatically invokes +'git rerere' upon exiting with a failed automerge and 'git rerere' +records the hand resolve when it is a new conflict, or reuses the earlier hand +resolve when it is not. 'git commit' also invokes 'git rerere' +when committing a merge result. What this means is that you do +not have to do anything special yourself (besides enabling +the rerere.enabled config variable). + +In our example, when you do the test merge, the manual +resolution is recorded, and it will be reused when you do the +actual merge later with the updated master and topic branch, as long +as the recorded resolution is still applicable. + +The information 'git rerere' records is also used when running +'git rebase'. After blowing away the test merge and continuing +development on the topic branch: + +------------ + o---*---o-------o---o topic + / + o---o---o---*---o---o---o---o master + + $ git rebase master topic + + o---*---o-------o---o topic + / + o---o---o---*---o---o---o---o master +------------ + +you could run `git rebase master topic`, to bring yourself +up to date before your topic is ready to be sent upstream. +This would result in falling back to a three-way merge, and it +would conflict the same way as the test merge you resolved earlier. +'git rerere' will be run by 'git rebase' to help you resolve this +conflict. + +[NOTE] 'git rerere' relies on the conflict markers in the file to +detect the conflict. If the file already contains lines that look the +same as lines with conflict markers, 'git rerere' may fail to record a +conflict resolution. To work around this, the `conflict-marker-size` +setting in linkgit:gitattributes[5] can be used. + +GIT +--- +Part of the linkgit:git[1] suite |