summaryrefslogtreecommitdiff
path: root/Documentation
diff options
context:
space:
mode:
authorLibravatar Johannes Schindelin <johannes.schindelin@gmx.de>2018-04-25 14:29:40 +0200
committerLibravatar Junio C Hamano <gitster@pobox.com>2018-04-26 12:28:43 +0900
commit7543f6f4441a0ec76460a54f90ab8674fe424786 (patch)
tree86fdce64f8c39f3994e2c6635f2cd3070b17d434 /Documentation
parentpull: accept --rebase=merges to recreate the branch topology (diff)
downloadtgif-7543f6f4441a0ec76460a54f90ab8674fe424786.tar.xz
rebase -i: introduce --rebase-merges=[no-]rebase-cousins
When running `git rebase --rebase-merges` non-interactively with an ancestor of HEAD as <upstream> (or leaving the todo list unmodified), we would ideally recreate the exact same commits as before the rebase. However, if there are commits in the commit range <upstream>.. that do not have <upstream> as direct ancestor (i.e. if `git log <upstream>..` would show commits that are omitted by `git log --ancestry-path <upstream>..`), this is currently not the case: we would turn them into commits that have <upstream> as direct ancestor. Let's illustrate that with a diagram: C / \ A - B - E - F \ / D Currently, after running `git rebase -i --rebase-merges B`, the new branch structure would be (pay particular attention to the commit `D`): --- C' -- / \ A - B ------ E' - F' \ / D' This is not really preserving the branch topology from before! The reason is that the commit `D` does not have `B` as ancestor, and therefore it gets rebased onto `B`. This is unintuitive behavior. Even worse, when recreating branch structure, most use cases would appear to want cousins *not* to be rebased onto the new base commit. For example, Git for Windows (the heaviest user of the Git garden shears, which served as the blueprint for --rebase-merges) frequently merges branches from `next` early, and these branches certainly do *not* want to be rebased. In the example above, the desired outcome would look like this: --- C' -- / \ A - B ------ E' - F' \ / -- D' -- Let's introduce the term "cousins" for such commits ("D" in the example), and let's not rebase them by default. For hypothetical use cases where cousins *do* need to be rebased, `git rebase --rebase=merges=rebase-cousins` needs to be used. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'Documentation')
-rw-r--r--Documentation/git-rebase.txt15
1 files changed, 11 insertions, 4 deletions
diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 7f1756f1eb..fe681d6928 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -380,7 +380,7 @@ rebase.instructionFormat. A customized instruction format will automatically
have the long commit hash prepended to the format.
-r::
---rebase-merges::
+--rebase-merges[=(rebase-cousins|no-rebase-cousins)]::
By default, a rebase will simply drop merge commits from the todo
list, and put the rebased commits into a single, linear branch.
With `--rebase-merges`, the rebase will instead try to preserve
@@ -389,9 +389,16 @@ have the long commit hash prepended to the format.
manual amendments in these merge commits will have to be
resolved/re-applied manually.
+
-This mode is similar in spirit to `--preserve-merges`, but in contrast to
-that option works well in interactive rebases: commits can be reordered,
-inserted and dropped at will.
+By default, or when `no-rebase-cousins` was specified, commits which do not
+have `<upstream>` as direct ancestor will keep their original branch point,
+i.e. commits that would be excluded by gitlink:git-log[1]'s
+`--ancestry-path` option will keep their original ancestry by default. If
+the `rebase-cousins` mode is turned on, such commits are instead rebased
+onto `<upstream>` (or `<onto>`, if specified).
++
+The `--rebase-merges` mode is similar in spirit to `--preserve-merges`, but
+in contrast to that option works well in interactive rebases: commits can be
+reordered, inserted and dropped at will.
+
It is currently only possible to recreate the merge commits using the
`recursive` merge strategy; Different merge strategies can be used only via