Merge branch 'js/advise-when-skipping-cherry-picked'
"git rebase" by default skips changes that are equivalent to commits that are already in the history the branch is rebased onto; give messages when this happens to let the users be aware of skipped commits, and also teach them how to tell "rebase" to keep duplicated changes. * js/advise-when-skipping-cherry-picked: sequencer: advise if skipping cherry-picked commit
This commit is contained in:
@ -44,6 +44,9 @@ advice.*::
|
|||||||
Shown when linkgit:git-push[1] rejects a forced update of
|
Shown when linkgit:git-push[1] rejects a forced update of
|
||||||
a branch when its remote-tracking ref has updates that we
|
a branch when its remote-tracking ref has updates that we
|
||||||
do not have locally.
|
do not have locally.
|
||||||
|
skippedCherryPicks::
|
||||||
|
Shown when linkgit:git-rebase[1] skips a commit that has already
|
||||||
|
been cherry-picked onto the upstream branch.
|
||||||
statusAheadBehind::
|
statusAheadBehind::
|
||||||
Shown when linkgit:git-status[1] computes the ahead/behind
|
Shown when linkgit:git-status[1] computes the ahead/behind
|
||||||
counts for a local ref compared to its remote tracking ref,
|
counts for a local ref compared to its remote tracking ref,
|
||||||
|
@ -79,9 +79,10 @@ remain the checked-out branch.
|
|||||||
|
|
||||||
If the upstream branch already contains a change you have made (e.g.,
|
If the upstream branch already contains a change you have made (e.g.,
|
||||||
because you mailed a patch which was applied upstream), then that commit
|
because you mailed a patch which was applied upstream), then that commit
|
||||||
will be skipped. For example, running `git rebase master` on the
|
will be skipped and warnings will be issued (if the `merge` backend is
|
||||||
following history (in which `A'` and `A` introduce the same set of changes,
|
used). For example, running `git rebase master` on the following
|
||||||
but have different committer information):
|
history (in which `A'` and `A` introduce the same set of changes, but
|
||||||
|
have different committer information):
|
||||||
|
|
||||||
------------
|
------------
|
||||||
A---B---C topic
|
A---B---C topic
|
||||||
@ -312,7 +313,10 @@ See also INCOMPATIBLE OPTIONS below.
|
|||||||
By default (or if `--no-reapply-cherry-picks` is given), these commits
|
By default (or if `--no-reapply-cherry-picks` is given), these commits
|
||||||
will be automatically dropped. Because this necessitates reading all
|
will be automatically dropped. Because this necessitates reading all
|
||||||
upstream commits, this can be expensive in repos with a large number
|
upstream commits, this can be expensive in repos with a large number
|
||||||
of upstream commits that need to be read.
|
of upstream commits that need to be read. When using the `merge`
|
||||||
|
backend, warnings will be issued for each dropped commit (unless
|
||||||
|
`--quiet` is given). Advice will also be issued unless
|
||||||
|
`advice.skippedCherryPicks` is set to false (see linkgit:git-config[1]).
|
||||||
+
|
+
|
||||||
`--reapply-cherry-picks` allows rebase to forgo reading all upstream
|
`--reapply-cherry-picks` allows rebase to forgo reading all upstream
|
||||||
commits, potentially improving performance.
|
commits, potentially improving performance.
|
||||||
|
3
advice.c
3
advice.c
@ -34,6 +34,7 @@ int advice_checkout_ambiguous_remote_branch_name = 1;
|
|||||||
int advice_submodule_alternate_error_strategy_die = 1;
|
int advice_submodule_alternate_error_strategy_die = 1;
|
||||||
int advice_add_ignored_file = 1;
|
int advice_add_ignored_file = 1;
|
||||||
int advice_add_empty_pathspec = 1;
|
int advice_add_empty_pathspec = 1;
|
||||||
|
int advice_skipped_cherry_picks = 1;
|
||||||
|
|
||||||
static int advice_use_color = -1;
|
static int advice_use_color = -1;
|
||||||
static char advice_colors[][COLOR_MAXLEN] = {
|
static char advice_colors[][COLOR_MAXLEN] = {
|
||||||
@ -96,6 +97,7 @@ static struct {
|
|||||||
{ "submoduleAlternateErrorStrategyDie", &advice_submodule_alternate_error_strategy_die },
|
{ "submoduleAlternateErrorStrategyDie", &advice_submodule_alternate_error_strategy_die },
|
||||||
{ "addIgnoredFile", &advice_add_ignored_file },
|
{ "addIgnoredFile", &advice_add_ignored_file },
|
||||||
{ "addEmptyPathspec", &advice_add_empty_pathspec },
|
{ "addEmptyPathspec", &advice_add_empty_pathspec },
|
||||||
|
{ "skippedCherryPicks", &advice_skipped_cherry_picks },
|
||||||
|
|
||||||
/* make this an alias for backward compatibility */
|
/* make this an alias for backward compatibility */
|
||||||
{ "pushNonFastForward", &advice_push_update_rejected }
|
{ "pushNonFastForward", &advice_push_update_rejected }
|
||||||
@ -133,6 +135,7 @@ static struct {
|
|||||||
[ADVICE_RM_HINTS] = { "rmHints", 1 },
|
[ADVICE_RM_HINTS] = { "rmHints", 1 },
|
||||||
[ADVICE_SEQUENCER_IN_USE] = { "sequencerInUse", 1 },
|
[ADVICE_SEQUENCER_IN_USE] = { "sequencerInUse", 1 },
|
||||||
[ADVICE_SET_UPSTREAM_FAILURE] = { "setUpstreamFailure", 1 },
|
[ADVICE_SET_UPSTREAM_FAILURE] = { "setUpstreamFailure", 1 },
|
||||||
|
[ADVICE_SKIPPED_CHERRY_PICKS] = { "skippedCherryPicks", 1 },
|
||||||
[ADVICE_STATUS_AHEAD_BEHIND_WARNING] = { "statusAheadBehindWarning", 1 },
|
[ADVICE_STATUS_AHEAD_BEHIND_WARNING] = { "statusAheadBehindWarning", 1 },
|
||||||
[ADVICE_STATUS_HINTS] = { "statusHints", 1 },
|
[ADVICE_STATUS_HINTS] = { "statusHints", 1 },
|
||||||
[ADVICE_STATUS_U_OPTION] = { "statusUoption", 1 },
|
[ADVICE_STATUS_U_OPTION] = { "statusUoption", 1 },
|
||||||
|
2
advice.h
2
advice.h
@ -35,6 +35,7 @@ extern int advice_checkout_ambiguous_remote_branch_name;
|
|||||||
extern int advice_submodule_alternate_error_strategy_die;
|
extern int advice_submodule_alternate_error_strategy_die;
|
||||||
extern int advice_add_ignored_file;
|
extern int advice_add_ignored_file;
|
||||||
extern int advice_add_empty_pathspec;
|
extern int advice_add_empty_pathspec;
|
||||||
|
extern int advice_skipped_cherry_picks;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* To add a new advice, you need to:
|
* To add a new advice, you need to:
|
||||||
@ -75,6 +76,7 @@ extern int advice_add_empty_pathspec;
|
|||||||
ADVICE_SUBMODULE_ALTERNATE_ERROR_STRATEGY_DIE,
|
ADVICE_SUBMODULE_ALTERNATE_ERROR_STRATEGY_DIE,
|
||||||
ADVICE_UPDATE_SPARSE_PATH,
|
ADVICE_UPDATE_SPARSE_PATH,
|
||||||
ADVICE_WAITING_FOR_EDITOR,
|
ADVICE_WAITING_FOR_EDITOR,
|
||||||
|
ADVICE_SKIPPED_CHERRY_PICKS,
|
||||||
};
|
};
|
||||||
|
|
||||||
int git_default_advice_config(const char *var, const char *value);
|
int git_default_advice_config(const char *var, const char *value);
|
||||||
|
@ -405,6 +405,7 @@ static int run_sequencer_rebase(struct rebase_options *opts,
|
|||||||
flags |= opts->root_with_onto ? TODO_LIST_ROOT_WITH_ONTO : 0;
|
flags |= opts->root_with_onto ? TODO_LIST_ROOT_WITH_ONTO : 0;
|
||||||
flags |= command == ACTION_SHORTEN_OIDS ? TODO_LIST_SHORTEN_IDS : 0;
|
flags |= command == ACTION_SHORTEN_OIDS ? TODO_LIST_SHORTEN_IDS : 0;
|
||||||
flags |= opts->reapply_cherry_picks ? TODO_LIST_REAPPLY_CHERRY_PICKS : 0;
|
flags |= opts->reapply_cherry_picks ? TODO_LIST_REAPPLY_CHERRY_PICKS : 0;
|
||||||
|
flags |= opts->flags & REBASE_NO_QUIET ? TODO_LIST_WARN_SKIPPED_CHERRY_PICKS : 0;
|
||||||
|
|
||||||
switch (command) {
|
switch (command) {
|
||||||
case ACTION_NONE: {
|
case ACTION_NONE: {
|
||||||
|
22
sequencer.c
22
sequencer.c
@ -5110,6 +5110,7 @@ static int make_script_with_merges(struct pretty_print_context *pp,
|
|||||||
int keep_empty = flags & TODO_LIST_KEEP_EMPTY;
|
int keep_empty = flags & TODO_LIST_KEEP_EMPTY;
|
||||||
int rebase_cousins = flags & TODO_LIST_REBASE_COUSINS;
|
int rebase_cousins = flags & TODO_LIST_REBASE_COUSINS;
|
||||||
int root_with_onto = flags & TODO_LIST_ROOT_WITH_ONTO;
|
int root_with_onto = flags & TODO_LIST_ROOT_WITH_ONTO;
|
||||||
|
int skipped_commit = 0;
|
||||||
struct strbuf buf = STRBUF_INIT, oneline = STRBUF_INIT;
|
struct strbuf buf = STRBUF_INIT, oneline = STRBUF_INIT;
|
||||||
struct strbuf label = STRBUF_INIT;
|
struct strbuf label = STRBUF_INIT;
|
||||||
struct commit_list *commits = NULL, **tail = &commits, *iter;
|
struct commit_list *commits = NULL, **tail = &commits, *iter;
|
||||||
@ -5160,8 +5161,13 @@ static int make_script_with_merges(struct pretty_print_context *pp,
|
|||||||
oidset_insert(&interesting, &commit->object.oid);
|
oidset_insert(&interesting, &commit->object.oid);
|
||||||
|
|
||||||
is_empty = is_original_commit_empty(commit);
|
is_empty = is_original_commit_empty(commit);
|
||||||
if (!is_empty && (commit->object.flags & PATCHSAME))
|
if (!is_empty && (commit->object.flags & PATCHSAME)) {
|
||||||
|
if (flags & TODO_LIST_WARN_SKIPPED_CHERRY_PICKS)
|
||||||
|
warning(_("skipped previously applied commit %s"),
|
||||||
|
short_commit_name(commit));
|
||||||
|
skipped_commit = 1;
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
if (is_empty && !keep_empty)
|
if (is_empty && !keep_empty)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -5225,6 +5231,9 @@ static int make_script_with_merges(struct pretty_print_context *pp,
|
|||||||
oidcpy(&entry->entry.oid, &commit->object.oid);
|
oidcpy(&entry->entry.oid, &commit->object.oid);
|
||||||
oidmap_put(&commit2todo, entry);
|
oidmap_put(&commit2todo, entry);
|
||||||
}
|
}
|
||||||
|
if (skipped_commit)
|
||||||
|
advise_if_enabled(ADVICE_SKIPPED_CHERRY_PICKS,
|
||||||
|
_("use --reapply-cherry-picks to include skipped commits"));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Second phase:
|
* Second phase:
|
||||||
@ -5345,6 +5354,7 @@ int sequencer_make_script(struct repository *r, struct strbuf *out, int argc,
|
|||||||
const char *insn = flags & TODO_LIST_ABBREVIATE_CMDS ? "p" : "pick";
|
const char *insn = flags & TODO_LIST_ABBREVIATE_CMDS ? "p" : "pick";
|
||||||
int rebase_merges = flags & TODO_LIST_REBASE_MERGES;
|
int rebase_merges = flags & TODO_LIST_REBASE_MERGES;
|
||||||
int reapply_cherry_picks = flags & TODO_LIST_REAPPLY_CHERRY_PICKS;
|
int reapply_cherry_picks = flags & TODO_LIST_REAPPLY_CHERRY_PICKS;
|
||||||
|
int skipped_commit = 0;
|
||||||
|
|
||||||
repo_init_revisions(r, &revs, NULL);
|
repo_init_revisions(r, &revs, NULL);
|
||||||
revs.verbose_header = 1;
|
revs.verbose_header = 1;
|
||||||
@ -5380,8 +5390,13 @@ int sequencer_make_script(struct repository *r, struct strbuf *out, int argc,
|
|||||||
while ((commit = get_revision(&revs))) {
|
while ((commit = get_revision(&revs))) {
|
||||||
int is_empty = is_original_commit_empty(commit);
|
int is_empty = is_original_commit_empty(commit);
|
||||||
|
|
||||||
if (!is_empty && (commit->object.flags & PATCHSAME))
|
if (!is_empty && (commit->object.flags & PATCHSAME)) {
|
||||||
|
if (flags & TODO_LIST_WARN_SKIPPED_CHERRY_PICKS)
|
||||||
|
warning(_("skipped previously applied commit %s"),
|
||||||
|
short_commit_name(commit));
|
||||||
|
skipped_commit = 1;
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
if (is_empty && !keep_empty)
|
if (is_empty && !keep_empty)
|
||||||
continue;
|
continue;
|
||||||
strbuf_addf(out, "%s %s ", insn,
|
strbuf_addf(out, "%s %s ", insn,
|
||||||
@ -5391,6 +5406,9 @@ int sequencer_make_script(struct repository *r, struct strbuf *out, int argc,
|
|||||||
strbuf_addf(out, " %c empty", comment_line_char);
|
strbuf_addf(out, " %c empty", comment_line_char);
|
||||||
strbuf_addch(out, '\n');
|
strbuf_addch(out, '\n');
|
||||||
}
|
}
|
||||||
|
if (skipped_commit)
|
||||||
|
advise_if_enabled(ADVICE_SKIPPED_CHERRY_PICKS,
|
||||||
|
_("use --reapply-cherry-picks to include skipped commits"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,6 +156,7 @@ int sequencer_remove_state(struct replay_opts *opts);
|
|||||||
*/
|
*/
|
||||||
#define TODO_LIST_ROOT_WITH_ONTO (1U << 6)
|
#define TODO_LIST_ROOT_WITH_ONTO (1U << 6)
|
||||||
#define TODO_LIST_REAPPLY_CHERRY_PICKS (1U << 7)
|
#define TODO_LIST_REAPPLY_CHERRY_PICKS (1U << 7)
|
||||||
|
#define TODO_LIST_WARN_SKIPPED_CHERRY_PICKS (1U << 8)
|
||||||
|
|
||||||
int sequencer_make_script(struct repository *r, struct strbuf *out, int argc,
|
int sequencer_make_script(struct repository *r, struct strbuf *out, int argc,
|
||||||
const char **argv, unsigned flags);
|
const char **argv, unsigned flags);
|
||||||
|
Reference in New Issue
Block a user