Skip to content

Commit

Permalink
git-rebase.txt: add more details about behavioral differences of back…
Browse files Browse the repository at this point in the history
…ends

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
newren authored and gitster committed Feb 16, 2020
1 parent befb89c commit be50c93
Showing 1 changed file with 80 additions and 5 deletions.
85 changes: 80 additions & 5 deletions Documentation/git-rebase.txt
Expand Up @@ -416,7 +416,7 @@ with `--keep-base` in order to drop those commits from your branch.

--ignore-whitespace::
--whitespace=<option>::
These flag are passed to the 'git apply' program
These flags are passed to the 'git apply' program
(see linkgit:git-apply[1]) that applies the patch.
+
See also INCOMPATIBLE OPTIONS below.
Expand Down Expand Up @@ -563,8 +563,8 @@ The following options:

* --committer-date-is-author-date
* --ignore-date
* --whitespace
* --ignore-whitespace
* --whitespace
* -C

are incompatible with the following options:
Expand Down Expand Up @@ -615,9 +615,84 @@ handling commits that become empty.
Directory rename detection
~~~~~~~~~~~~~~~~~~~~~~~~~~

Directory rename heuristics are enabled in the merge and interactive
backends. Due to the lack of accurate tree information, directory
rename detection is disabled in the am backend.
Due to the lack of accurate tree information (arising from
constructing fake ancestors with the limited information available in
patches), directory rename detection is disabled in the am backend.
Disabled directory rename detection means that if one side of history
renames a directory and the other adds new files to the old directory,
then the new files will be left behind in the old directory without
any warning at the time of rebasing that you may want to move these
files into the new directory.

Directory rename detection works with the merge and interactive
backends to provide you warnings in such cases.

Context
~~~~~~~

The am backend works by creating a sequence of patches (by calling
`format-patch` internally), and then applying the patches in sequence
(calling `am` internally). Patches are composed of multiple hunks,
each with line numbers, a context region, and the actual changes. The
line numbers have to be taken with some fuzz, since the other side
will likely have inserted or deleted lines earlier in the file. The
context region is meant to help find how to adjust the line numbers in
order to apply the changes to the right lines. However, if multiple
areas of the code have the same surrounding lines of context, the
wrong one can be picked. There are real-world cases where this has
caused commits to be reapplied incorrectly with no conflicts reported.
Setting diff.context to a larger value may prevent such types of
problems, but increases the chance of spurious conflicts (since it
will require more lines of matching context to apply).

The interactive backend works with a full copy of each relevant file,
insulating it from these types of problems.

Labelling of conflicts markers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

When there are content conflicts, the merge machinery tries to
annotate each side's conflict markers with the commits where the
content came from. Since the am backend drops the original
information about the rebased commits and their parents (and instead
generates new fake commits based off limited information in the
generated patches), those commits cannot be identified; instead it has
to fall back to a commit summary. Also, when merge.conflictStyle is
set to diff3, the am backend will use "constructed merge base" to
label the content from the merge base, and thus provide no information
about the merge base commit whatsoever.

The interactive backend works with the full commits on both sides of
history and thus has no such limitations.

Hooks
~~~~~

The am backend has not traditionally called the post-commit hook,
while the merge/interactive backend has. However, this was by
accident of implementation rather than by design. Both backends
should have the same behavior, though it is not clear which one is
correct.

Miscellaneous differences
~~~~~~~~~~~~~~~~~~~~~~~~~

There are a few more behavioral differences that most folks would
probably consider inconsequential but which are mentioned for
completeness:

* Reflog: The two backends will use different wording when describing
the changes made in the reflog, though both will make use of the
word "rebase".

* Progress, informational, and error messages: The two backends
provide slightly different progress and informational messages.
Also, the am backend writes error messages (such as "Your files
would be overwritten...") to stdout, while the interactive backend
writes them to stderr.

* State directories: The two backends keep their state in different
directories under .git/

include::merge-strategies.txt[]

Expand Down

0 comments on commit be50c93

Please sign in to comment.