Skip to content

Commit 0ce5a69

Browse files
committed
Merge branch 'en/rebase-consistency'
"git rebase" behaved slightly differently depending on which one of the three backends gets used; this has been documented and an effort to make them more uniform has begun. * en/rebase-consistency: git-rebase: make --allow-empty-message the default t3401: add directory rename testcases for rebase and am git-rebase.txt: document behavioral differences between modes directory-rename-detection.txt: technical docs on abilities and limitations git-rebase.txt: address confusion between --no-ff vs --force-rebase git-rebase: error out when incompatible options passed t3422: new testcases for checking when incompatible options passed git-rebase.sh: update help messages a bit git-rebase.txt: document incompatible options
2 parents 392b3dd + b00bf1c commit 0ce5a69

7 files changed

+462
-42
lines changed

Documentation/git-rebase.txt

Lines changed: 108 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -243,11 +243,15 @@ leave out at most one of A and B, in which case it defaults to HEAD.
243243
--keep-empty::
244244
Keep the commits that do not change anything from its
245245
parents in the result.
246+
+
247+
See also INCOMPATIBLE OPTIONS below.
246248

247249
--allow-empty-message::
248250
By default, rebasing commits with an empty message will fail.
249251
This option overrides that behavior, allowing commits with empty
250252
messages to be rebased.
253+
+
254+
See also INCOMPATIBLE OPTIONS below.
251255

252256
--skip::
253257
Restart the rebasing process by skipping the current patch.
@@ -271,6 +275,8 @@ branch on top of the <upstream> branch. Because of this, when a merge
271275
conflict happens, the side reported as 'ours' is the so-far rebased
272276
series, starting with <upstream>, and 'theirs' is the working branch. In
273277
other words, the sides are swapped.
278+
+
279+
See also INCOMPATIBLE OPTIONS below.
274280

275281
-s <strategy>::
276282
--strategy=<strategy>::
@@ -280,15 +286,19 @@ other words, the sides are swapped.
280286
+
281287
Because 'git rebase' replays each commit from the working branch
282288
on top of the <upstream> branch using the given strategy, using
283-
the 'ours' strategy simply discards all patches from the <branch>,
289+
the 'ours' strategy simply empties all patches from the <branch>,
284290
which makes little sense.
291+
+
292+
See also INCOMPATIBLE OPTIONS below.
285293

286294
-X <strategy-option>::
287295
--strategy-option=<strategy-option>::
288296
Pass the <strategy-option> through to the merge strategy.
289297
This implies `--merge` and, if no strategy has been
290298
specified, `-s recursive`. Note the reversal of 'ours' and
291299
'theirs' as noted above for the `-m` option.
300+
+
301+
See also INCOMPATIBLE OPTIONS below.
292302

293303
-S[<keyid>]::
294304
--gpg-sign[=<keyid>]::
@@ -324,17 +334,21 @@ which makes little sense.
324334
and after each change. When fewer lines of surrounding
325335
context exist they all must match. By default no context is
326336
ever ignored.
337+
+
338+
See also INCOMPATIBLE OPTIONS below.
327339

328-
-f::
340+
--no-ff::
329341
--force-rebase::
330-
Force a rebase even if the current branch is up to date and
331-
the command without `--force` would return without doing anything.
342+
-f::
343+
Individually replay all rebased commits instead of fast-forwarding
344+
over the unchanged ones. This ensures that the entire history of
345+
the rebased branch is composed of new commits.
332346
+
333-
You may find this (or --no-ff with an interactive rebase) helpful after
334-
reverting a topic branch merge, as this option recreates the topic branch with
335-
fresh commits so it can be remerged successfully without needing to "revert
336-
the reversion" (see the
337-
link:howto/revert-a-faulty-merge.html[revert-a-faulty-merge How-To] for details).
347+
You may find this helpful after reverting a topic branch merge, as this option
348+
recreates the topic branch with fresh commits so it can be remerged
349+
successfully without needing to "revert the reversion" (see the
350+
link:howto/revert-a-faulty-merge.html[revert-a-faulty-merge How-To] for
351+
details).
338352

339353
--fork-point::
340354
--no-fork-point::
@@ -355,19 +369,22 @@ default is `--no-fork-point`, otherwise the default is `--fork-point`.
355369
--whitespace=<option>::
356370
These flag are passed to the 'git apply' program
357371
(see linkgit:git-apply[1]) that applies the patch.
358-
Incompatible with the --interactive option.
372+
+
373+
See also INCOMPATIBLE OPTIONS below.
359374

360375
--committer-date-is-author-date::
361376
--ignore-date::
362377
These flags are passed to 'git am' to easily change the dates
363378
of the rebased commits (see linkgit:git-am[1]).
364-
Incompatible with the --interactive option.
379+
+
380+
See also INCOMPATIBLE OPTIONS below.
365381

366382
--signoff::
367383
Add a Signed-off-by: trailer to all the rebased commits. Note
368384
that if `--interactive` is given then only commits marked to be
369-
picked, edited or reworded will have the trailer added. Incompatible
370-
with the `--preserve-merges` option.
385+
picked, edited or reworded will have the trailer added.
386+
+
387+
See also INCOMPATIBLE OPTIONS below.
371388

372389
-i::
373390
--interactive::
@@ -378,6 +395,8 @@ default is `--no-fork-point`, otherwise the default is `--fork-point`.
378395
The commit list format can be changed by setting the configuration option
379396
rebase.instructionFormat. A customized instruction format will automatically
380397
have the long commit hash prepended to the format.
398+
+
399+
See also INCOMPATIBLE OPTIONS below.
381400

382401
-r::
383402
--rebase-merges[=(rebase-cousins|no-rebase-cousins)]::
@@ -404,7 +423,7 @@ It is currently only possible to recreate the merge commits using the
404423
`recursive` merge strategy; Different merge strategies can be used only via
405424
explicit `exec git merge -s <strategy> [...]` commands.
406425
+
407-
See also REBASING MERGES below.
426+
See also REBASING MERGES and INCOMPATIBLE OPTIONS below.
408427

409428
-p::
410429
--preserve-merges::
@@ -415,6 +434,8 @@ See also REBASING MERGES below.
415434
This uses the `--interactive` machinery internally, but combining it
416435
with the `--interactive` option explicitly is generally not a good
417436
idea unless you know what you are doing (see BUGS below).
437+
+
438+
See also INCOMPATIBLE OPTIONS below.
418439

419440
-x <cmd>::
420441
--exec <cmd>::
@@ -437,6 +458,8 @@ squash/fixup series.
437458
+
438459
This uses the `--interactive` machinery internally, but it can be run
439460
without an explicit `--interactive`.
461+
+
462+
See also INCOMPATIBLE OPTIONS below.
440463

441464
--root::
442465
Rebase all commits reachable from <branch>, instead of
@@ -447,6 +470,8 @@ without an explicit `--interactive`.
447470
When used together with both --onto and --preserve-merges,
448471
'all' root commits will be rewritten to have <newbase> as parent
449472
instead.
473+
+
474+
See also INCOMPATIBLE OPTIONS below.
450475

451476
--autosquash::
452477
--no-autosquash::
@@ -461,11 +486,11 @@ without an explicit `--interactive`.
461486
too. The recommended way to create fixup/squash commits is by using
462487
the `--fixup`/`--squash` options of linkgit:git-commit[1].
463488
+
464-
This option is only valid when the `--interactive` option is used.
465-
+
466489
If the `--autosquash` option is enabled by default using the
467490
configuration variable `rebase.autoSquash`, this option can be
468491
used to override and disable this setting.
492+
+
493+
See also INCOMPATIBLE OPTIONS below.
469494

470495
--autostash::
471496
--no-autostash::
@@ -475,17 +500,73 @@ used to override and disable this setting.
475500
with care: the final stash application after a successful
476501
rebase might result in non-trivial conflicts.
477502

478-
--no-ff::
479-
With --interactive, cherry-pick all rebased commits instead of
480-
fast-forwarding over the unchanged ones. This ensures that the
481-
entire history of the rebased branch is composed of new commits.
482-
+
483-
Without --interactive, this is a synonym for --force-rebase.
484-
+
485-
You may find this helpful after reverting a topic branch merge, as this option
486-
recreates the topic branch with fresh commits so it can be remerged
487-
successfully without needing to "revert the reversion" (see the
488-
link:howto/revert-a-faulty-merge.html[revert-a-faulty-merge How-To] for details).
503+
INCOMPATIBLE OPTIONS
504+
--------------------
505+
506+
git-rebase has many flags that are incompatible with each other,
507+
predominantly due to the fact that it has three different underlying
508+
implementations:
509+
510+
* one based on linkgit:git-am[1] (the default)
511+
* one based on git-merge-recursive (merge backend)
512+
* one based on linkgit:git-cherry-pick[1] (interactive backend)
513+
514+
Flags only understood by the am backend:
515+
516+
* --committer-date-is-author-date
517+
* --ignore-date
518+
* --whitespace
519+
* --ignore-whitespace
520+
* -C
521+
522+
Flags understood by both merge and interactive backends:
523+
524+
* --merge
525+
* --strategy
526+
* --strategy-option
527+
* --allow-empty-message
528+
529+
Flags only understood by the interactive backend:
530+
531+
* --[no-]autosquash
532+
* --rebase-merges
533+
* --preserve-merges
534+
* --interactive
535+
* --exec
536+
* --keep-empty
537+
* --autosquash
538+
* --edit-todo
539+
* --root when used in combination with --onto
540+
541+
Other incompatible flag pairs:
542+
543+
* --preserve-merges and --interactive
544+
* --preserve-merges and --signoff
545+
* --preserve-merges and --rebase-merges
546+
* --rebase-merges and --strategy
547+
* --rebase-merges and --strategy-option
548+
549+
BEHAVIORAL DIFFERENCES
550+
-----------------------
551+
552+
* empty commits:
553+
554+
am-based rebase will drop any "empty" commits, whether the
555+
commit started empty (had no changes relative to its parent to
556+
start with) or ended empty (all changes were already applied
557+
upstream in other commits).
558+
559+
merge-based rebase does the same.
560+
561+
interactive-based rebase will by default drop commits that
562+
started empty and halt if it hits a commit that ended up empty.
563+
The `--keep-empty` option exists for interactive rebases to allow
564+
it to keep commits that started empty.
565+
566+
* directory rename detection:
567+
568+
merge-based and interactive-based rebases work fine with
569+
directory rename detection. am-based rebases sometimes do not.
489570

490571
include::merge-strategies.txt[]
491572

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
Directory rename detection
2+
==========================
3+
4+
Rename detection logic in diffcore-rename that checks for renames of
5+
individual files is aggregated and analyzed in merge-recursive for cases
6+
where combinations of renames indicate that a full directory has been
7+
renamed.
8+
9+
Scope of abilities
10+
------------------
11+
12+
It is perhaps easiest to start with an example:
13+
14+
* When all of x/a, x/b and x/c have moved to z/a, z/b and z/c, it is
15+
likely that x/d added in the meantime would also want to move to z/d by
16+
taking the hint that the entire directory 'x' moved to 'z'.
17+
18+
More interesting possibilities exist, though, such as:
19+
20+
* one side of history renames x -> z, and the other renames some file to
21+
x/e, causing the need for the merge to do a transitive rename.
22+
23+
* one side of history renames x -> z, but also renames all files within
24+
x. For example, x/a -> z/alpha, x/b -> z/bravo, etc.
25+
26+
* both 'x' and 'y' being merged into a single directory 'z', with a
27+
directory rename being detected for both x->z and y->z.
28+
29+
* not all files in a directory being renamed to the same location;
30+
i.e. perhaps most the files in 'x' are now found under 'z', but a few
31+
are found under 'w'.
32+
33+
* a directory being renamed, which also contained a subdirectory that was
34+
renamed to some entirely different location. (And perhaps the inner
35+
directory itself contained inner directories that were renamed to yet
36+
other locations).
37+
38+
* combinations of the above; see t/t6043-merge-rename-directories.sh for
39+
various interesting cases.
40+
41+
Limitations -- applicability of directory renames
42+
-------------------------------------------------
43+
44+
In order to prevent edge and corner cases resulting in either conflicts
45+
that cannot be represented in the index or which might be too complex for
46+
users to try to understand and resolve, a couple basic rules limit when
47+
directory rename detection applies:
48+
49+
1) If a given directory still exists on both sides of a merge, we do
50+
not consider it to have been renamed.
51+
52+
2) If a subset of to-be-renamed files have a file or directory in the
53+
way (or would be in the way of each other), "turn off" the directory
54+
rename for those specific sub-paths and report the conflict to the
55+
user.
56+
57+
3) If the other side of history did a directory rename to a path that
58+
your side of history renamed away, then ignore that particular
59+
rename from the other side of history for any implicit directory
60+
renames (but warn the user).
61+
62+
Limitations -- detailed rules and testcases
63+
-------------------------------------------
64+
65+
t/t6043-merge-rename-directories.sh contains extensive tests and commentary
66+
which generate and explore the rules listed above. It also lists a few
67+
additional rules:
68+
69+
a) If renames split a directory into two or more others, the directory
70+
with the most renames, "wins".
71+
72+
b) Avoid directory-rename-detection for a path, if that path is the
73+
source of a rename on either side of a merge.
74+
75+
c) Only apply implicit directory renames to directories if the other side
76+
of history is the one doing the renaming.
77+
78+
Limitations -- support in different commands
79+
--------------------------------------------
80+
81+
Directory rename detection is supported by 'merge' and 'cherry-pick'.
82+
Other git commands which users might be surprised to see limited or no
83+
directory rename detection support in:
84+
85+
* diff
86+
87+
Folks have requested in the past that `git diff` detect directory
88+
renames and somehow simplify its output. It is not clear whether this
89+
would be desirable or how the output should be simplified, so this was
90+
simply not implemented. Further, to implement this, directory rename
91+
detection logic would need to move from merge-recursive to
92+
diffcore-rename.
93+
94+
* am
95+
96+
git-am tries to avoid a full three way merge, instead calling
97+
git-apply. That prevents us from detecting renames at all, which may
98+
defeat the directory rename detection. There is a fallback, though; if
99+
the initial git-apply fails and the user has specified the -3 option,
100+
git-am will fall back to a three way merge. However, git-am lacks the
101+
necessary information to do a "real" three way merge. Instead, it has
102+
to use build_fake_ancestor() to get a merge base that is missing files
103+
whose rename may have been important to detect for directory rename
104+
detection to function.
105+
106+
* rebase
107+
108+
Since am-based rebases work by first generating a bunch of patches
109+
(which no longer record what the original commits were and thus don't
110+
have the necessary info from which we can find a real merge-base), and
111+
then calling git-am, this implies that am-based rebases will not always
112+
successfully detect directory renames either (see the 'am' section
113+
above). merged-based rebases (rebase -m) and cherry-pick-based rebases
114+
(rebase -i) are not affected by this shortcoming, and fully support
115+
directory rename detection.

0 commit comments

Comments
 (0)