зеркало из https://github.com/microsoft/git.git
178 строки
6.0 KiB
Plaintext
178 строки
6.0 KiB
Plaintext
|
git-rerere(1)
|
||
|
=============
|
||
|
|
||
|
NAME
|
||
|
----
|
||
|
git-rerere - Reuse recorded resolve
|
||
|
|
||
|
SYNOPSIS
|
||
|
--------
|
||
|
'git-rerere'
|
||
|
|
||
|
|
||
|
DESCRIPTION
|
||
|
-----------
|
||
|
|
||
|
In a workflow that employs relatively long lived topic branches,
|
||
|
the developer sometimes needs to resolve the same conflict over
|
||
|
and over again until the topic branches are done (either merged
|
||
|
to the "release" branch, or sent out and accepted upstream).
|
||
|
|
||
|
This command helps this process by recording conflicted
|
||
|
automerge results and corresponding hand-resolve results on the
|
||
|
initial manual merge, and later by noticing the same automerge
|
||
|
results and applying the previously recorded hand resolution.
|
||
|
|
||
|
[NOTE]
|
||
|
You need to create `$GIT_DIR/rr-cache` directory to enable this
|
||
|
command.
|
||
|
|
||
|
DISCUSSION
|
||
|
----------
|
||
|
|
||
|
When your topic branch modifies 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 checkout topic
|
||
|
$ git pull . 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 checkout topic
|
||
|
$ git pull . master
|
||
|
$ ... work on both topic and master branches
|
||
|
$ git checkout master
|
||
|
$ git pull . 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 checkout topic
|
||
|
$ git pull . master
|
||
|
$ git reset --hard HEAD^ ;# rewind the test merge
|
||
|
$ ... work on both topic and master branches
|
||
|
$ git checkout master
|
||
|
$ git pull . 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, often this conflict is the
|
||
|
same conflict you resolved when you created the test merge you
|
||
|
blew away. `git-rerere` command helps you to resolve this final
|
||
|
conflicted merge using the information from your earlier hand
|
||
|
resolve.
|
||
|
|
||
|
Running `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 records the resolved state of these
|
||
|
files. Suppose you did this when you created the test merge of
|
||
|
master into the topic branch.
|
||
|
|
||
|
Next time, running `git-rerere` after seeing a conflicted
|
||
|
automerge, if the conflict is the same as the earlier one
|
||
|
recorded, it is noticed and a three-way merge between the
|
||
|
earlier conflicted automerge, the earlier manual resolution, and
|
||
|
the current conflicted automerge is performed by the command.
|
||
|
If this three-way merge resolves cleanly, the result is written
|
||
|
out to your working tree file, so you would 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 update-index` when you are
|
||
|
satisfied.
|
||
|
|
||
|
As a convenience measure, `git-merge` automatically invokes
|
||
|
`git-rerere` when it exits with a failed automerge, which
|
||
|
records it if it is a new conflict, or reuses the earlier hand
|
||
|
resolve when it is not. `git-commit` also invokes `git-rerere`
|
||
|
when recording a merge result. What this means is that you do
|
||
|
not have to do anything special yourself (Note: you still have
|
||
|
to create `$GIT_DIR/rr-cache` directory to enable this command).
|
||
|
|
||
|
In our example, when you did the test merge, the manual
|
||
|
resolution is recorded, and it will be reused when you do the
|
||
|
actual merge later with updated master and topic branch, as long
|
||
|
as the earlier 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 keep yourself
|
||
|
up-to-date even before your topic is ready to be sent upstream.
|
||
|
This would result in falling back to three-way merge, and it
|
||
|
would conflict the same way the test merge you resolved earlier.
|
||
|
`git-rerere` is run by `git rebase` to help you resolve this
|
||
|
conflict.
|
||
|
|
||
|
|
||
|
Author
|
||
|
------
|
||
|
Written by Junio C Hamano <junkio@cox.net>
|
||
|
|
||
|
GIT
|
||
|
---
|
||
|
Part of the gitlink:git[7] suite
|