Skip to content

Commit 2c6e5b3

Browse files
committed
Merge branch 'en/rebase-incompatible-opts'
"git rebase" often ignored incompatible options instead of complaining, which has been corrected. * en/rebase-incompatible-opts: rebase: provide better error message for apply options vs. merge config rebase: put rebase_options initialization in single place rebase: fix formatting of rebase --reapply-cherry-picks option in docs rebase: clarify the OPT_CMDMODE incompatibilities rebase: add coverage of other incompatible options rebase: fix incompatiblity checks for --[no-]reapply-cherry-picks rebase: fix docs about incompatibilities with --root rebase: remove --allow-empty-message from incompatible opts rebase: flag --apply and --merge as incompatible rebase: mark --update-refs as requiring the merge backend
2 parents c7757b2 + eddfcd8 commit 2c6e5b3

File tree

3 files changed

+163
-64
lines changed

3 files changed

+163
-64
lines changed

Documentation/git-rebase.txt

Lines changed: 39 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,39 @@ Alternatively, you can undo the 'git rebase' with
208208

209209
git rebase --abort
210210

211+
MODE OPTIONS
212+
------------
213+
214+
The options in this section cannot be used with any other option,
215+
including not with each other:
216+
217+
--continue::
218+
Restart the rebasing process after having resolved a merge conflict.
219+
220+
--skip::
221+
Restart the rebasing process by skipping the current patch.
222+
223+
--abort::
224+
Abort the rebase operation and reset HEAD to the original
225+
branch. If `<branch>` was provided when the rebase operation was
226+
started, then `HEAD` will be reset to `<branch>`. Otherwise `HEAD`
227+
will be reset to where it was when the rebase operation was
228+
started.
229+
230+
--quit::
231+
Abort the rebase operation but `HEAD` is not reset back to the
232+
original branch. The index and working tree are also left
233+
unchanged as a result. If a temporary stash entry was created
234+
using `--autostash`, it will be saved to the stash list.
235+
236+
--edit-todo::
237+
Edit the todo list during an interactive rebase.
238+
239+
--show-current-patch::
240+
Show the current patch in an interactive rebase or when rebase
241+
is stopped because of conflicts. This is the equivalent of
242+
`git show REBASE_HEAD`.
243+
211244
OPTIONS
212245
-------
213246
--onto <newbase>::
@@ -249,22 +282,6 @@ See also INCOMPATIBLE OPTIONS below.
249282
<branch>::
250283
Working branch; defaults to `HEAD`.
251284

252-
--continue::
253-
Restart the rebasing process after having resolved a merge conflict.
254-
255-
--abort::
256-
Abort the rebase operation and reset HEAD to the original
257-
branch. If `<branch>` was provided when the rebase operation was
258-
started, then `HEAD` will be reset to `<branch>`. Otherwise `HEAD`
259-
will be reset to where it was when the rebase operation was
260-
started.
261-
262-
--quit::
263-
Abort the rebase operation but `HEAD` is not reset back to the
264-
original branch. The index and working tree are also left
265-
unchanged as a result. If a temporary stash entry was created
266-
using `--autostash`, it will be saved to the stash list.
267-
268285
--apply::
269286
Use applying strategies to rebase (calling `git-am`
270287
internally). This option may become a no-op in the future
@@ -321,7 +338,6 @@ See also INCOMPATIBLE OPTIONS below.
321338
upstream changes, the behavior towards them is controlled by
322339
the `--empty` flag.)
323340
+
324-
325341
In the absence of `--keep-base` (or if `--no-reapply-cherry-picks` is
326342
given), these commits will be automatically dropped. Because this
327343
necessitates reading all upstream commits, this can be expensive in
@@ -330,7 +346,6 @@ read. When using the 'merge' backend, warnings will be issued for each
330346
dropped commit (unless `--quiet` is given). Advice will also be issued
331347
unless `advice.skippedCherryPicks` is set to false (see
332348
linkgit:git-config[1]).
333-
334349
+
335350
`--reapply-cherry-picks` allows rebase to forgo reading all upstream
336351
commits, potentially improving performance.
@@ -345,17 +360,6 @@ See also INCOMPATIBLE OPTIONS below.
345360
+
346361
See also INCOMPATIBLE OPTIONS below.
347362

348-
--skip::
349-
Restart the rebasing process by skipping the current patch.
350-
351-
--edit-todo::
352-
Edit the todo list during an interactive rebase.
353-
354-
--show-current-patch::
355-
Show the current patch in an interactive rebase or when rebase
356-
is stopped because of conflicts. This is the equivalent of
357-
`git show REBASE_HEAD`.
358-
359363
-m::
360364
--merge::
361365
Using merging strategies to rebase (default).
@@ -574,10 +578,7 @@ See also INCOMPATIBLE OPTIONS below.
574578
--root::
575579
Rebase all commits reachable from `<branch>`, instead of
576580
limiting them with an `<upstream>`. This allows you to rebase
577-
the root commit(s) on a branch. When used with `--onto`, it
578-
will skip changes already contained in `<newbase>` (instead of
579-
`<upstream>`) whereas without `--onto` it will operate on every
580-
change.
581+
the root commit(s) on a branch.
581582
+
582583
See also INCOMPATIBLE OPTIONS below.
583584

@@ -630,6 +631,8 @@ start would be overridden by the presence of
630631
+
631632
If the configuration variable `rebase.updateRefs` is set, then this option
632633
can be used to override and disable this setting.
634+
+
635+
See also INCOMPATIBLE OPTIONS below.
633636

634637
INCOMPATIBLE OPTIONS
635638
--------------------
@@ -645,17 +648,15 @@ are incompatible with the following options:
645648
* --merge
646649
* --strategy
647650
* --strategy-option
648-
* --allow-empty-message
649-
* --[no-]autosquash
651+
* --autosquash
650652
* --rebase-merges
651653
* --interactive
652654
* --exec
653655
* --no-keep-empty
654656
* --empty=
655-
* --reapply-cherry-picks
656-
* --edit-todo
657+
* --[no-]reapply-cherry-picks when used without --keep-base
657658
* --update-refs
658-
* --root when used in combination with --onto
659+
* --root when used without --onto
659660

660661
In addition, the following pairs of options are incompatible:
661662

builtin/rebase.c

Lines changed: 58 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ struct rebase_options {
122122
int reapply_cherry_picks;
123123
int fork_point;
124124
int update_refs;
125+
int config_autosquash;
126+
int config_update_refs;
125127
};
126128

127129
#define REBASE_OPTIONS_INIT { \
@@ -134,6 +136,12 @@ struct rebase_options {
134136
.exec = STRING_LIST_INIT_NODUP, \
135137
.git_format_patch_opt = STRBUF_INIT, \
136138
.fork_point = -1, \
139+
.reapply_cherry_picks = -1, \
140+
.allow_empty_message = 1, \
141+
.autosquash = -1, \
142+
.config_autosquash = -1, \
143+
.update_refs = -1, \
144+
.config_update_refs = -1, \
137145
}
138146

139147
static struct replay_opts get_replay_opts(const struct rebase_options *opts)
@@ -776,7 +784,7 @@ static int rebase_config(const char *var, const char *value, void *data)
776784
}
777785

778786
if (!strcmp(var, "rebase.autosquash")) {
779-
opts->autosquash = git_config_bool(var, value);
787+
opts->config_autosquash = git_config_bool(var, value);
780788
return 0;
781789
}
782790

@@ -793,7 +801,7 @@ static int rebase_config(const char *var, const char *value, void *data)
793801
}
794802

795803
if (!strcmp(var, "rebase.updaterefs")) {
796-
opts->update_refs = git_config_bool(var, value);
804+
opts->config_update_refs = git_config_bool(var, value);
797805
return 0;
798806
}
799807

@@ -907,6 +915,9 @@ static int parse_opt_am(const struct option *opt, const char *arg, int unset)
907915
BUG_ON_OPT_NEG(unset);
908916
BUG_ON_OPT_ARG(arg);
909917

918+
if (opts->type != REBASE_UNSPECIFIED && opts->type != REBASE_APPLY)
919+
die(_("apply options and merge options cannot be used together"));
920+
910921
opts->type = REBASE_APPLY;
911922

912923
return 0;
@@ -920,8 +931,10 @@ static int parse_opt_merge(const struct option *opt, const char *arg, int unset)
920931
BUG_ON_OPT_NEG(unset);
921932
BUG_ON_OPT_ARG(arg);
922933

923-
if (!is_merge(opts))
924-
opts->type = REBASE_MERGE;
934+
if (opts->type != REBASE_UNSPECIFIED && opts->type != REBASE_MERGE)
935+
die(_("apply options and merge options cannot be used together"));
936+
937+
opts->type = REBASE_MERGE;
925938

926939
return 0;
927940
}
@@ -935,6 +948,9 @@ static int parse_opt_interactive(const struct option *opt, const char *arg,
935948
BUG_ON_OPT_NEG(unset);
936949
BUG_ON_OPT_ARG(arg);
937950

951+
if (opts->type != REBASE_UNSPECIFIED && opts->type != REBASE_MERGE)
952+
die(_("apply options and merge options cannot be used together"));
953+
938954
opts->type = REBASE_MERGE;
939955
opts->flags |= REBASE_INTERACTIVE_EXPLICIT;
940956

@@ -1150,8 +1166,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
11501166
prepare_repo_settings(the_repository);
11511167
the_repository->settings.command_requires_full_index = 0;
11521168

1153-
options.reapply_cherry_picks = -1;
1154-
options.allow_empty_message = 1;
11551169
git_config(rebase_config, &options);
11561170
/* options.gpg_sign_opt will be either "-S" or NULL */
11571171
gpg_sign = options.gpg_sign_opt ? "" : NULL;
@@ -1216,13 +1230,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
12161230
if (options.fork_point < 0)
12171231
options.fork_point = 0;
12181232
}
1219-
/*
1220-
* --keep-base defaults to --reapply-cherry-picks to avoid losing
1221-
* commits when using this option.
1222-
*/
1223-
if (options.reapply_cherry_picks < 0)
1224-
options.reapply_cherry_picks = keep_base;
1225-
12261233
if (options.root && options.fork_point > 0)
12271234
die(_("options '%s' and '%s' cannot be used together"), "--root", "--fork-point");
12281235

@@ -1365,7 +1372,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
13651372
if ((options.flags & REBASE_INTERACTIVE_EXPLICIT) ||
13661373
(options.action != ACTION_NONE) ||
13671374
(options.exec.nr > 0) ||
1368-
options.autosquash) {
1375+
(options.autosquash == -1 && options.config_autosquash == 1) ||
1376+
options.autosquash == 1) {
13691377
allow_preemptive_ff = 0;
13701378
}
13711379
if (options.committer_date_is_author_date || options.ignore_date)
@@ -1398,12 +1406,27 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
13981406
if (options.empty != EMPTY_UNSPECIFIED)
13991407
imply_merge(&options, "--empty");
14001408

1401-
/*
1402-
* --keep-base implements --reapply-cherry-picks by altering upstream so
1403-
* it works with both backends.
1404-
*/
1405-
if (options.reapply_cherry_picks && !keep_base)
1406-
imply_merge(&options, "--reapply-cherry-picks");
1409+
if (options.reapply_cherry_picks < 0)
1410+
/*
1411+
* We default to --no-reapply-cherry-picks unless
1412+
* --keep-base is given; when --keep-base is given, we want
1413+
* to default to --reapply-cherry-picks.
1414+
*/
1415+
options.reapply_cherry_picks = keep_base;
1416+
else if (!keep_base)
1417+
/*
1418+
* The apply backend always searches for and drops cherry
1419+
* picks. This is often not wanted with --keep-base, so
1420+
* --keep-base allows --reapply-cherry-picks to be
1421+
* simulated by altering the upstream such that
1422+
* cherry-picks cannot be detected and thus all commits are
1423+
* reapplied. Thus, --[no-]reapply-cherry-picks is
1424+
* supported when --keep-base is specified, but not when
1425+
* --keep-base is left out.
1426+
*/
1427+
imply_merge(&options, options.reapply_cherry_picks ?
1428+
"--reapply-cherry-picks" :
1429+
"--no-reapply-cherry-picks");
14071430

14081431
if (gpg_sign)
14091432
options.gpg_sign_opt = xstrfmt("-S%s", gpg_sign);
@@ -1483,15 +1506,29 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
14831506
if (strcmp(options.git_am_opts.v[i], "-q"))
14841507
break;
14851508

1486-
if (i >= 0) {
1509+
if (i >= 0 || options.type == REBASE_APPLY) {
14871510
if (is_merge(&options))
14881511
die(_("apply options and merge options "
14891512
"cannot be used together"));
1513+
else if (options.autosquash == -1 && options.config_autosquash == 1)
1514+
die(_("apply options are incompatible with rebase.autosquash. Consider adding --no-autosquash"));
1515+
else if (options.update_refs == -1 && options.config_update_refs == 1)
1516+
die(_("apply options are incompatible with rebase.updateRefs. Consider adding --no-update-refs"));
14901517
else
14911518
options.type = REBASE_APPLY;
14921519
}
14931520
}
14941521

1522+
if (options.update_refs == 1)
1523+
imply_merge(&options, "--update-refs");
1524+
options.update_refs = (options.update_refs >= 0) ? options.update_refs :
1525+
((options.config_update_refs >= 0) ? options.config_update_refs : 0);
1526+
1527+
if (options.autosquash == 1)
1528+
imply_merge(&options, "--autosquash");
1529+
options.autosquash = (options.autosquash >= 0) ? options.autosquash :
1530+
((options.config_autosquash >= 0) ? options.config_autosquash : 0);
1531+
14951532
if (options.type == REBASE_UNSPECIFIED) {
14961533
if (!strcmp(options.default_backend, "merge"))
14971534
imply_merge(&options, "--merge");

0 commit comments

Comments
 (0)