Skip to content

Commit 17381ab

Browse files
committed
Merge branch 'bl/cherry-pick-empty'
Allow git-cherry-pick(1) to automatically drop redundant commits via a new `--empty` option, similar to the `--empty` options for git-rebase(1) and git-am(1). Includes a soft deprecation of `--keep-redundant-commits` as well as some related docs changes and sequencer code cleanup. * bl/cherry-pick-empty: cherry-pick: add `--empty` for more robust redundant commit handling cherry-pick: enforce `--keep-redundant-commits` incompatibility sequencer: do not require `allow_empty` for redundant commit options sequencer: handle unborn branch with `--allow-empty` rebase: update `--empty=ask` to `--empty=stop` docs: clean up `--empty` formatting in git-rebase(1) and git-am(1) docs: address inaccurate `--empty` default with `--exec`
2 parents d988e80 + ec79d76 commit 17381ab

10 files changed

+286
-68
lines changed

Documentation/git-am.txt

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,19 @@ OPTIONS
6666
--quoted-cr=<action>::
6767
This flag will be passed down to 'git mailinfo' (see linkgit:git-mailinfo[1]).
6868

69-
--empty=(stop|drop|keep)::
70-
By default, or when the option is set to 'stop', the command
71-
errors out on an input e-mail message lacking a patch
72-
and stops in the middle of the current am session. When this
73-
option is set to 'drop', skip such an e-mail message instead.
74-
When this option is set to 'keep', create an empty commit,
75-
recording the contents of the e-mail message as its log.
69+
--empty=(drop|keep|stop)::
70+
How to handle an e-mail message lacking a patch:
71+
+
72+
--
73+
`drop`;;
74+
The e-mail message will be skipped.
75+
`keep`;;
76+
An empty commit will be created, with the contents of the e-mail
77+
message as its log.
78+
`stop`;;
79+
The command will fail, stopping in the middle of the current `am`
80+
session. This is the default behavior.
81+
--
7682

7783
-m::
7884
--message-id::

Documentation/git-cherry-pick.txt

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -131,20 +131,36 @@ effect to your index in a row.
131131
even without this option. Note also, that use of this option only
132132
keeps commits that were initially empty (i.e. the commit recorded the
133133
same tree as its parent). Commits which are made empty due to a
134-
previous commit are dropped. To force the inclusion of those commits
135-
use `--keep-redundant-commits`.
134+
previous commit will cause the cherry-pick to fail. To force the
135+
inclusion of those commits, use `--empty=keep`.
136136

137137
--allow-empty-message::
138138
By default, cherry-picking a commit with an empty message will fail.
139139
This option overrides that behavior, allowing commits with empty
140140
messages to be cherry picked.
141141

142+
--empty=(drop|keep|stop)::
143+
How to handle commits being cherry-picked that are redundant with
144+
changes already in the current history.
145+
+
146+
--
147+
`drop`;;
148+
The commit will be dropped.
149+
`keep`;;
150+
The commit will be kept. Implies `--allow-empty`.
151+
`stop`;;
152+
The cherry-pick will stop when the commit is applied, allowing
153+
you to examine the commit. This is the default behavior.
154+
--
155+
+
156+
Note that `--empty=drop` and `--empty=stop` only specify how to handle a
157+
commit that was not initially empty, but rather became empty due to a previous
158+
commit. Commits that were initially empty will still cause the cherry-pick to
159+
fail unless one of `--empty=keep` or `--allow-empty` are specified.
160+
+
161+
142162
--keep-redundant-commits::
143-
If a commit being cherry picked duplicates a commit already in the
144-
current history, it will become empty. By default these
145-
redundant commits cause `cherry-pick` to stop so the user can
146-
examine the commit. This option overrides that behavior and
147-
creates an empty commit object. Implies `--allow-empty`.
163+
Deprecated synonym for `--empty=keep`.
148164

149165
--strategy=<strategy>::
150166
Use the given merge strategy. Should only be used once.

Documentation/git-rebase.txt

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -289,17 +289,25 @@ See also INCOMPATIBLE OPTIONS below.
289289
+
290290
See also INCOMPATIBLE OPTIONS below.
291291

292-
--empty=(drop|keep|ask)::
292+
--empty=(drop|keep|stop)::
293293
How to handle commits that are not empty to start and are not
294294
clean cherry-picks of any upstream commit, but which become
295295
empty after rebasing (because they contain a subset of already
296-
upstream changes). With drop (the default), commits that
297-
become empty are dropped. With keep, such commits are kept.
298-
With ask (implied by `--interactive`), the rebase will halt when
299-
an empty commit is applied allowing you to choose whether to
300-
drop it, edit files more, or just commit the empty changes.
301-
Other options, like `--exec`, will use the default of drop unless
302-
`-i`/`--interactive` is explicitly specified.
296+
upstream changes):
297+
+
298+
--
299+
`drop`;;
300+
The commit will be dropped. This is the default behavior.
301+
`keep`;;
302+
The commit will be kept. This option is implied when `--exec` is
303+
specified unless `-i`/`--interactive` is also specified.
304+
`stop`;;
305+
`ask`;;
306+
The rebase will halt when the commit is applied, allowing you to
307+
choose whether to drop it, edit files more, or just commit the empty
308+
changes. This option is implied when `-i`/`--interactive` is
309+
specified. `ask` is a deprecated synonym of `stop`.
310+
--
303311
+
304312
Note that commits which start empty are kept (unless `--no-keep-empty`
305313
is specified), and commits which are clean cherry-picks (as determined
@@ -704,7 +712,7 @@ be dropped automatically with `--no-keep-empty`).
704712
Similar to the apply backend, by default the merge backend drops
705713
commits that become empty unless `-i`/`--interactive` is specified (in
706714
which case it stops and asks the user what to do). The merge backend
707-
also has an `--empty=(drop|keep|ask)` option for changing the behavior
715+
also has an `--empty=(drop|keep|stop)` option for changing the behavior
708716
of handling commits that become empty.
709717

710718
Directory rename detection

builtin/rebase.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ enum empty_type {
5858
EMPTY_UNSPECIFIED = -1,
5959
EMPTY_DROP,
6060
EMPTY_KEEP,
61-
EMPTY_ASK
61+
EMPTY_STOP
6262
};
6363

6464
enum action {
@@ -945,10 +945,14 @@ static enum empty_type parse_empty_value(const char *value)
945945
return EMPTY_DROP;
946946
else if (!strcasecmp(value, "keep"))
947947
return EMPTY_KEEP;
948-
else if (!strcasecmp(value, "ask"))
949-
return EMPTY_ASK;
948+
else if (!strcasecmp(value, "stop"))
949+
return EMPTY_STOP;
950+
else if (!strcasecmp(value, "ask")) {
951+
warning(_("--empty=ask is deprecated; use '--empty=stop' instead."));
952+
return EMPTY_STOP;
953+
}
950954

951-
die(_("unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and \"ask\"."), value);
955+
die(_("unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and \"stop\"."), value);
952956
}
953957

954958
static int parse_opt_keep_empty(const struct option *opt, const char *arg,
@@ -1127,7 +1131,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
11271131
"instead of ignoring them"),
11281132
1, PARSE_OPT_HIDDEN),
11291133
OPT_RERERE_AUTOUPDATE(&options.allow_rerere_autoupdate),
1130-
OPT_CALLBACK_F(0, "empty", &options, "(drop|keep|ask)",
1134+
OPT_CALLBACK_F(0, "empty", &options, "(drop|keep|stop)",
11311135
N_("how to handle commits that become empty"),
11321136
PARSE_OPT_NONEG, parse_opt_empty),
11331137
OPT_CALLBACK_F('k', "keep-empty", &options, NULL,
@@ -1544,7 +1548,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
15441548

15451549
if (options.empty == EMPTY_UNSPECIFIED) {
15461550
if (options.flags & REBASE_INTERACTIVE_EXPLICIT)
1547-
options.empty = EMPTY_ASK;
1551+
options.empty = EMPTY_STOP;
15481552
else if (options.exec.nr > 0)
15491553
options.empty = EMPTY_KEEP;
15501554
else

builtin/revert.c

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,31 @@ static const char * const *revert_or_cherry_pick_usage(struct replay_opts *opts)
4343
return opts->action == REPLAY_REVERT ? revert_usage : cherry_pick_usage;
4444
}
4545

46+
enum empty_action {
47+
EMPTY_COMMIT_UNSPECIFIED = -1,
48+
STOP_ON_EMPTY_COMMIT, /* output errors and stop in the middle of a cherry-pick */
49+
DROP_EMPTY_COMMIT, /* skip with a notice message */
50+
KEEP_EMPTY_COMMIT, /* keep recording as empty commits */
51+
};
52+
53+
static int parse_opt_empty(const struct option *opt, const char *arg, int unset)
54+
{
55+
int *opt_value = opt->value;
56+
57+
BUG_ON_OPT_NEG(unset);
58+
59+
if (!strcmp(arg, "stop"))
60+
*opt_value = STOP_ON_EMPTY_COMMIT;
61+
else if (!strcmp(arg, "drop"))
62+
*opt_value = DROP_EMPTY_COMMIT;
63+
else if (!strcmp(arg, "keep"))
64+
*opt_value = KEEP_EMPTY_COMMIT;
65+
else
66+
return error(_("invalid value for '%s': '%s'"), "--empty", arg);
67+
68+
return 0;
69+
}
70+
4671
static int option_parse_m(const struct option *opt,
4772
const char *arg, int unset)
4873
{
@@ -85,6 +110,7 @@ static int run_sequencer(int argc, const char **argv, const char *prefix,
85110
const char * const * usage_str = revert_or_cherry_pick_usage(opts);
86111
const char *me = action_name(opts);
87112
const char *cleanup_arg = NULL;
113+
enum empty_action empty_opt = EMPTY_COMMIT_UNSPECIFIED;
88114
int cmd = 0;
89115
struct option base_options[] = {
90116
OPT_CMDMODE(0, "quit", &cmd, N_("end revert or cherry-pick sequence"), 'q'),
@@ -114,7 +140,10 @@ static int run_sequencer(int argc, const char **argv, const char *prefix,
114140
OPT_BOOL(0, "ff", &opts->allow_ff, N_("allow fast-forward")),
115141
OPT_BOOL(0, "allow-empty", &opts->allow_empty, N_("preserve initially empty commits")),
116142
OPT_BOOL(0, "allow-empty-message", &opts->allow_empty_message, N_("allow commits with empty messages")),
117-
OPT_BOOL(0, "keep-redundant-commits", &opts->keep_redundant_commits, N_("keep redundant, empty commits")),
143+
OPT_BOOL(0, "keep-redundant-commits", &opts->keep_redundant_commits, N_("deprecated: use --empty=keep instead")),
144+
OPT_CALLBACK_F(0, "empty", &empty_opt, "(stop|drop|keep)",
145+
N_("how to handle commits that become empty"),
146+
PARSE_OPT_NONEG, parse_opt_empty),
118147
OPT_END(),
119148
};
120149
options = parse_options_concat(options, cp_extra);
@@ -134,6 +163,11 @@ static int run_sequencer(int argc, const char **argv, const char *prefix,
134163
prepare_repo_settings(the_repository);
135164
the_repository->settings.command_requires_full_index = 0;
136165

166+
if (opts->action == REPLAY_PICK) {
167+
opts->drop_redundant_commits = (empty_opt == DROP_EMPTY_COMMIT);
168+
opts->keep_redundant_commits = opts->keep_redundant_commits || (empty_opt == KEEP_EMPTY_COMMIT);
169+
}
170+
137171
/* implies allow_empty */
138172
if (opts->keep_redundant_commits)
139173
opts->allow_empty = 1;
@@ -167,6 +201,8 @@ static int run_sequencer(int argc, const char **argv, const char *prefix,
167201
"--ff", opts->allow_ff,
168202
"--rerere-autoupdate", opts->allow_rerere_auto == RERERE_AUTOUPDATE,
169203
"--no-rerere-autoupdate", opts->allow_rerere_auto == RERERE_NOAUTOUPDATE,
204+
"--keep-redundant-commits", opts->keep_redundant_commits,
205+
"--empty", empty_opt != EMPTY_COMMIT_UNSPECIFIED,
170206
NULL);
171207
}
172208

sequencer.c

Lines changed: 41 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -787,29 +787,42 @@ static struct object_id *get_cache_tree_oid(struct index_state *istate)
787787
static int is_index_unchanged(struct repository *r)
788788
{
789789
struct object_id head_oid, *cache_tree_oid;
790+
const struct object_id *head_tree_oid;
790791
struct commit *head_commit;
791792
struct index_state *istate = r->index;
793+
const char *head_name;
794+
795+
if (!resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, &head_oid, NULL)) {
796+
/* Check to see if this is an unborn branch */
797+
head_name = resolve_ref_unsafe("HEAD",
798+
RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
799+
&head_oid, NULL);
800+
if (!head_name ||
801+
!starts_with(head_name, "refs/heads/") ||
802+
!is_null_oid(&head_oid))
803+
return error(_("could not resolve HEAD commit"));
804+
head_tree_oid = the_hash_algo->empty_tree;
805+
} else {
806+
head_commit = lookup_commit(r, &head_oid);
792807

793-
if (!resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, &head_oid, NULL))
794-
return error(_("could not resolve HEAD commit"));
795-
796-
head_commit = lookup_commit(r, &head_oid);
808+
/*
809+
* If head_commit is NULL, check_commit, called from
810+
* lookup_commit, would have indicated that head_commit is not
811+
* a commit object already. repo_parse_commit() will return failure
812+
* without further complaints in such a case. Otherwise, if
813+
* the commit is invalid, repo_parse_commit() will complain. So
814+
* there is nothing for us to say here. Just return failure.
815+
*/
816+
if (repo_parse_commit(r, head_commit))
817+
return -1;
797818

798-
/*
799-
* If head_commit is NULL, check_commit, called from
800-
* lookup_commit, would have indicated that head_commit is not
801-
* a commit object already. repo_parse_commit() will return failure
802-
* without further complaints in such a case. Otherwise, if
803-
* the commit is invalid, repo_parse_commit() will complain. So
804-
* there is nothing for us to say here. Just return failure.
805-
*/
806-
if (repo_parse_commit(r, head_commit))
807-
return -1;
819+
head_tree_oid = get_commit_tree_oid(head_commit);
820+
}
808821

809822
if (!(cache_tree_oid = get_cache_tree_oid(istate)))
810823
return -1;
811824

812-
return oideq(cache_tree_oid, get_commit_tree_oid(head_commit));
825+
return oideq(cache_tree_oid, head_tree_oid);
813826
}
814827

815828
static int write_author_script(const char *message)
@@ -1736,34 +1749,25 @@ static int allow_empty(struct repository *r,
17361749
int index_unchanged, originally_empty;
17371750

17381751
/*
1739-
* Four cases:
1740-
*
1741-
* (1) we do not allow empty at all and error out.
1752+
* For a commit that is initially empty, allow_empty determines if it
1753+
* should be kept or not
17421754
*
1743-
* (2) we allow ones that were initially empty, and
1744-
* just drop the ones that become empty
1745-
*
1746-
* (3) we allow ones that were initially empty, but
1747-
* halt for the ones that become empty;
1748-
*
1749-
* (4) we allow both.
1755+
* For a commit that becomes empty, keep_redundant_commits and
1756+
* drop_redundant_commits determine whether the commit should be kept or
1757+
* dropped. If neither is specified, halt.
17501758
*/
1751-
if (!opts->allow_empty)
1752-
return 0; /* let "git commit" barf as necessary */
1753-
17541759
index_unchanged = is_index_unchanged(r);
17551760
if (index_unchanged < 0)
17561761
return index_unchanged;
17571762
if (!index_unchanged)
17581763
return 0; /* we do not have to say --allow-empty */
17591764

1760-
if (opts->keep_redundant_commits)
1761-
return 1;
1762-
17631765
originally_empty = is_original_commit_empty(commit);
17641766
if (originally_empty < 0)
17651767
return originally_empty;
17661768
if (originally_empty)
1769+
return opts->allow_empty;
1770+
else if (opts->keep_redundant_commits)
17671771
return 1;
17681772
else if (opts->drop_redundant_commits)
17691773
return 2;
@@ -2943,6 +2947,9 @@ static int populate_opts_cb(const char *key, const char *value,
29432947
else if (!strcmp(key, "options.allow-empty-message"))
29442948
opts->allow_empty_message =
29452949
git_config_bool_or_int(key, value, ctx->kvi, &error_flag);
2950+
else if (!strcmp(key, "options.drop-redundant-commits"))
2951+
opts->drop_redundant_commits =
2952+
git_config_bool_or_int(key, value, ctx->kvi, &error_flag);
29462953
else if (!strcmp(key, "options.keep-redundant-commits"))
29472954
opts->keep_redundant_commits =
29482955
git_config_bool_or_int(key, value, ctx->kvi, &error_flag);
@@ -3487,6 +3494,9 @@ static int save_opts(struct replay_opts *opts)
34873494
if (opts->allow_empty_message)
34883495
res |= git_config_set_in_file_gently(opts_file,
34893496
"options.allow-empty-message", "true");
3497+
if (opts->drop_redundant_commits)
3498+
res |= git_config_set_in_file_gently(opts_file,
3499+
"options.drop-redundant-commits", "true");
34903500
if (opts->keep_redundant_commits)
34913501
res |= git_config_set_in_file_gently(opts_file,
34923502
"options.keep-redundant-commits", "true");

0 commit comments

Comments
 (0)