* [PATCH 1/5] sequencer: sort options load/save by struct position
2017-01-23 22:52 [PATCH 0/5] sequencer: allow skipping commits Giuseppe Bilotta
@ 2017-01-23 22:52 ` Giuseppe Bilotta
2017-01-23 22:52 ` [PATCH 2/5] sequencer: save/load all options Giuseppe Bilotta
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Giuseppe Bilotta @ 2017-01-23 22:52 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Giuseppe Bilotta
No functional change. The order in which options are serialized and
reloaded is now the same in which they appear in the replay_opts
structure. This makes it easier to spot when we forget to
serialize/reload an option value.
Signed-off-by: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>
---
sequencer.c | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/sequencer.c b/sequencer.c
index 9adb7bbf1d..672c81b559 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -975,22 +975,22 @@ static int populate_opts_cb(const char *key, const char *value, void *data)
if (!value)
error_flag = 0;
- else if (!strcmp(key, "options.no-commit"))
- opts->no_commit = git_config_bool_or_int(key, value, &error_flag);
else if (!strcmp(key, "options.edit"))
opts->edit = git_config_bool_or_int(key, value, &error_flag);
- else if (!strcmp(key, "options.signoff"))
- opts->signoff = git_config_bool_or_int(key, value, &error_flag);
else if (!strcmp(key, "options.record-origin"))
opts->record_origin = git_config_bool_or_int(key, value, &error_flag);
+ else if (!strcmp(key, "options.no-commit"))
+ opts->no_commit = git_config_bool_or_int(key, value, &error_flag);
+ else if (!strcmp(key, "options.signoff"))
+ opts->signoff = git_config_bool_or_int(key, value, &error_flag);
else if (!strcmp(key, "options.allow-ff"))
opts->allow_ff = git_config_bool_or_int(key, value, &error_flag);
else if (!strcmp(key, "options.mainline"))
opts->mainline = git_config_int(key, value);
- else if (!strcmp(key, "options.strategy"))
- git_config_string_dup(&opts->strategy, key, value);
else if (!strcmp(key, "options.gpg-sign"))
git_config_string_dup(&opts->gpg_sign, key, value);
+ else if (!strcmp(key, "options.strategy"))
+ git_config_string_dup(&opts->strategy, key, value);
else if (!strcmp(key, "options.strategy-option")) {
ALLOC_GROW(opts->xopts, opts->xopts_nr + 1, opts->xopts_alloc);
opts->xopts[opts->xopts_nr++] = xstrdup(value);
@@ -1223,14 +1223,14 @@ static int save_opts(struct replay_opts *opts)
const char *opts_file = git_path_opts_file();
int res = 0;
- if (opts->no_commit)
- res |= git_config_set_in_file_gently(opts_file, "options.no-commit", "true");
if (opts->edit)
res |= git_config_set_in_file_gently(opts_file, "options.edit", "true");
- if (opts->signoff)
- res |= git_config_set_in_file_gently(opts_file, "options.signoff", "true");
if (opts->record_origin)
res |= git_config_set_in_file_gently(opts_file, "options.record-origin", "true");
+ if (opts->no_commit)
+ res |= git_config_set_in_file_gently(opts_file, "options.no-commit", "true");
+ if (opts->signoff)
+ res |= git_config_set_in_file_gently(opts_file, "options.signoff", "true");
if (opts->allow_ff)
res |= git_config_set_in_file_gently(opts_file, "options.allow-ff", "true");
if (opts->mainline) {
@@ -1239,10 +1239,10 @@ static int save_opts(struct replay_opts *opts)
res |= git_config_set_in_file_gently(opts_file, "options.mainline", buf.buf);
strbuf_release(&buf);
}
+ if (opts->gpg_sign)
+ res |= git_config_set_in_file_gently(opts_file, "options.gpg-sign", opts->gpg_sign);
if (opts->strategy)
res |= git_config_set_in_file_gently(opts_file, "options.strategy", opts->strategy);
- if (opts->gpg_sign)
- res |= git_config_set_in_file_gently(opts_file, "options.gpg-sign", opts->gpg_sign);
if (opts->xopts) {
int i;
for (i = 0; i < opts->xopts_nr; i++)
--
2.11.0.616.gd72966cf44.dirty
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/5] sequencer: save/load all options
2017-01-23 22:52 [PATCH 0/5] sequencer: allow skipping commits Giuseppe Bilotta
2017-01-23 22:52 ` [PATCH 1/5] sequencer: sort options load/save by struct position Giuseppe Bilotta
@ 2017-01-23 22:52 ` Giuseppe Bilotta
2017-01-23 22:52 ` [PATCH 3/5] cherry-pick: option to skip empty commits Giuseppe Bilotta
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Giuseppe Bilotta @ 2017-01-23 22:52 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Giuseppe Bilotta
Add the missing replay_opts to save_opts and populate_opts, so that an
interrupted cherry-pick will continue with the same setup it had before
the interruption.
Signed-off-by: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>
---
sequencer.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/sequencer.c b/sequencer.c
index 672c81b559..3d2f61c979 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -985,6 +985,14 @@ static int populate_opts_cb(const char *key, const char *value, void *data)
opts->signoff = git_config_bool_or_int(key, value, &error_flag);
else if (!strcmp(key, "options.allow-ff"))
opts->allow_ff = git_config_bool_or_int(key, value, &error_flag);
+ else if (!strcmp(key, "options.rerere-autoupdate"))
+ opts->allow_rerere_auto = git_config_bool_or_int(key, value, &error_flag);
+ else if (!strcmp(key, "options.allow-empty"))
+ opts->allow_empty = git_config_bool_or_int(key, value, &error_flag);
+ else if (!strcmp(key, "options.allow-empty-message"))
+ opts->allow_empty_message = git_config_bool_or_int(key, value, &error_flag);
+ else if (!strcmp(key, "options.keep-redundant-commits"))
+ opts->keep_redundant_commits = git_config_bool_or_int(key, value, &error_flag);
else if (!strcmp(key, "options.mainline"))
opts->mainline = git_config_int(key, value);
else if (!strcmp(key, "options.gpg-sign"))
@@ -1233,6 +1241,14 @@ static int save_opts(struct replay_opts *opts)
res |= git_config_set_in_file_gently(opts_file, "options.signoff", "true");
if (opts->allow_ff)
res |= git_config_set_in_file_gently(opts_file, "options.allow-ff", "true");
+ if (opts->allow_rerere_auto)
+ res |= git_config_set_in_file_gently(opts_file, "options.rerere-autoupdate", "true");
+ if (opts->allow_empty)
+ res |= git_config_set_in_file_gently(opts_file, "options.allow-empty", "true");
+ if (opts->allow_empty_message)
+ res |= git_config_set_in_file_gently(opts_file, "options.allow-empty-message", "true");
+ if (opts->keep_redundant_commits)
+ res |= git_config_set_in_file_gently(opts_file, "options.keep-redundant-commits", "true");
if (opts->mainline) {
struct strbuf buf = STRBUF_INIT;
strbuf_addf(&buf, "%d", opts->mainline);
--
2.11.0.616.gd72966cf44.dirty
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 3/5] cherry-pick: option to skip empty commits
2017-01-23 22:52 [PATCH 0/5] sequencer: allow skipping commits Giuseppe Bilotta
2017-01-23 22:52 ` [PATCH 1/5] sequencer: sort options load/save by struct position Giuseppe Bilotta
2017-01-23 22:52 ` [PATCH 2/5] sequencer: save/load all options Giuseppe Bilotta
@ 2017-01-23 22:52 ` Giuseppe Bilotta
2017-01-23 22:52 ` [PATCH 4/5] cherry-pick: allow skipping only redundant commits Giuseppe Bilotta
2017-01-23 22:52 ` [PATCH 5/5] sequencer: allow to --skip current commit Giuseppe Bilotta
4 siblings, 0 replies; 6+ messages in thread
From: Giuseppe Bilotta @ 2017-01-23 22:52 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Giuseppe Bilotta
This allows cherry-picking a set of commits, some of which may be
redundant, without stopping to ask for the user intervention.
Signed-off-by: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>
---
Documentation/git-cherry-pick.txt | 4 ++++
builtin/revert.c | 1 +
sequencer.c | 45 +++++++++++++++++++++++++++++++--------
sequencer.h | 1 +
4 files changed, 42 insertions(+), 9 deletions(-)
diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt
index d35d771fc8..ffced816d6 100644
--- a/Documentation/git-cherry-pick.txt
+++ b/Documentation/git-cherry-pick.txt
@@ -138,6 +138,10 @@ effect to your index in a row.
examine the commit. This option overrides that behavior and
creates an empty commit object. Implies `--allow-empty`.
+--skip-empty::
+ This option causes empty and redundant cherry-picked commits to
+ be skipped without requesting the user intervention.
+
--strategy=<strategy>::
Use the given merge strategy. Should only be used once.
See the MERGE STRATEGIES section in linkgit:git-merge[1]
diff --git a/builtin/revert.c b/builtin/revert.c
index 4ca5b51544..ffdd367f99 100644
--- a/builtin/revert.c
+++ b/builtin/revert.c
@@ -102,6 +102,7 @@ static int run_sequencer(int argc, const char **argv, struct replay_opts *opts)
OPT_BOOL(0, "allow-empty", &opts->allow_empty, N_("preserve initially empty commits")),
OPT_BOOL(0, "allow-empty-message", &opts->allow_empty_message, N_("allow commits with empty messages")),
OPT_BOOL(0, "keep-redundant-commits", &opts->keep_redundant_commits, N_("keep redundant, empty commits")),
+ OPT_BOOL(0, "skip-empty", &opts->skip_empty, N_("skip redundant, empty commits")),
OPT_END(),
};
options = parse_options_concat(options, cp_extra);
diff --git a/sequencer.c b/sequencer.c
index 3d2f61c979..9c01310162 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -550,22 +550,32 @@ static int is_original_commit_empty(struct commit *commit)
/*
* Do we run "git commit" with "--allow-empty"?
+ *
+ * Or do we just skip this empty commit?
+ *
+ * Returns 1 if a commit should be done with --allow-empty,
+ * 0 if a commit should be done without --allow-empty,
+ * 2 if no commit should be done at all (skip empty commit)
+ * negative values in case of error
+ *
*/
-static int allow_empty(struct replay_opts *opts, struct commit *commit)
+static int allow_or_skip_empty(struct replay_opts *opts, struct commit *commit)
{
int index_unchanged, empty_commit;
/*
- * Three cases:
+ * Four cases:
*
- * (1) we do not allow empty at all and error out.
+ * (1) we do not allow empty at all and error out;
*
- * (2) we allow ones that were initially empty, but
+ * (2) we skip empty commits altogether;
+ *
+ * (3) we allow ones that were initially empty, but
* forbid the ones that become empty;
*
- * (3) we allow both.
+ * (4) we allow both.
*/
- if (!opts->allow_empty)
+ if (!opts->allow_empty && !opts->skip_empty)
return 0; /* let "git commit" barf as necessary */
index_unchanged = is_index_unchanged();
@@ -574,6 +584,9 @@ static int allow_empty(struct replay_opts *opts, struct commit *commit)
if (!index_unchanged)
return 0; /* we do not have to say --allow-empty */
+ if (opts->skip_empty)
+ return 2;
+
if (opts->keep_redundant_commits)
return 1;
@@ -612,7 +625,7 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
const char *base_label, *next_label;
struct commit_message msg = { NULL, NULL, NULL, NULL };
struct strbuf msgbuf = STRBUF_INIT;
- int res, unborn = 0, allow;
+ int res = 0, unborn = 0, allow;
if (opts->no_commit) {
/*
@@ -771,12 +784,13 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
goto leave;
}
- allow = allow_empty(opts, commit);
+ allow = allow_or_skip_empty(opts, commit);
if (allow < 0) {
res = allow;
goto leave;
}
- if (!opts->no_commit)
+ /* allow == 2 means skip this commit */
+ if (allow != 2 && !opts->no_commit)
res = run_git_commit(opts->edit ? NULL : git_path_merge_msg(),
opts, allow, opts->edit, 0, 0);
@@ -993,6 +1007,8 @@ static int populate_opts_cb(const char *key, const char *value, void *data)
opts->allow_empty_message = git_config_bool_or_int(key, value, &error_flag);
else if (!strcmp(key, "options.keep-redundant-commits"))
opts->keep_redundant_commits = git_config_bool_or_int(key, value, &error_flag);
+ else if (!strcmp(key, "options.skip-empty"))
+ opts->skip_empty = git_config_bool_or_int(key, value, &error_flag);
else if (!strcmp(key, "options.mainline"))
opts->mainline = git_config_int(key, value);
else if (!strcmp(key, "options.gpg-sign"))
@@ -1249,6 +1265,8 @@ static int save_opts(struct replay_opts *opts)
res |= git_config_set_in_file_gently(opts_file, "options.allow-empty-message", "true");
if (opts->keep_redundant_commits)
res |= git_config_set_in_file_gently(opts_file, "options.keep-redundant-commits", "true");
+ if (opts->skip_empty)
+ res |= git_config_set_in_file_gently(opts_file, "options.skip-empty", "true");
if (opts->mainline) {
struct strbuf buf = STRBUF_INIT;
strbuf_addf(&buf, "%d", opts->mainline);
@@ -1322,6 +1340,14 @@ int sequencer_continue(struct replay_opts *opts)
if ((res = read_populate_todo(&todo_list, opts)))
goto release_todo_list;
+ /* check if there is something to commit */
+ res = is_index_unchanged();
+ if (res < 0)
+ goto release_todo_list;
+
+ if (res && opts->skip_empty)
+ goto skip_this_commit;
+
/* Verify that the conflict has been resolved */
if (file_exists(git_path_cherry_pick_head()) ||
file_exists(git_path_revert_head())) {
@@ -1333,6 +1359,7 @@ int sequencer_continue(struct replay_opts *opts)
res = error_dirty_index(opts);
goto release_todo_list;
}
+skip_this_commit:
todo_list.current++;
res = pick_commits(&todo_list, opts);
release_todo_list:
diff --git a/sequencer.h b/sequencer.h
index 7a513c576b..c747cfcfc7 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -23,6 +23,7 @@ struct replay_opts {
int allow_empty;
int allow_empty_message;
int keep_redundant_commits;
+ int skip_empty;
int mainline;
--
2.11.0.616.gd72966cf44.dirty
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 4/5] cherry-pick: allow skipping only redundant commits
2017-01-23 22:52 [PATCH 0/5] sequencer: allow skipping commits Giuseppe Bilotta
` (2 preceding siblings ...)
2017-01-23 22:52 ` [PATCH 3/5] cherry-pick: option to skip empty commits Giuseppe Bilotta
@ 2017-01-23 22:52 ` Giuseppe Bilotta
2017-01-23 22:52 ` [PATCH 5/5] sequencer: allow to --skip current commit Giuseppe Bilotta
4 siblings, 0 replies; 6+ messages in thread
From: Giuseppe Bilotta @ 2017-01-23 22:52 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Giuseppe Bilotta
This allows the preservation of originally empty commits with the
combination of flags --allow-empty --skip-redundant-commits.
Signed-off-by: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>
---
Documentation/git-cherry-pick.txt | 8 ++++-
builtin/revert.c | 18 +++++++++++-
sequencer.c | 62 ++++++++++++++++++++++++++++++---------
sequencer.h | 1 +
4 files changed, 73 insertions(+), 16 deletions(-)
diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt
index ffced816d6..147e0cde0c 100644
--- a/Documentation/git-cherry-pick.txt
+++ b/Documentation/git-cherry-pick.txt
@@ -138,9 +138,15 @@ effect to your index in a row.
examine the commit. This option overrides that behavior and
creates an empty commit object. Implies `--allow-empty`.
+--skip-redundant-commits::
+ Redundant commits will be skipped altogether. This does not
+ influence commits that were originally empty (see
+ `--allow-empty` and `--skip-empty`).
+
--skip-empty::
This option causes empty and redundant cherry-picked commits to
- be skipped without requesting the user intervention.
+ be skipped without requesting the user intervention. Implies
+ `--skip-redundant-commits`.
--strategy=<strategy>::
Use the given merge strategy. Should only be used once.
diff --git a/builtin/revert.c b/builtin/revert.c
index ffdd367f99..aca8a1d9d0 100644
--- a/builtin/revert.c
+++ b/builtin/revert.c
@@ -102,7 +102,8 @@ static int run_sequencer(int argc, const char **argv, struct replay_opts *opts)
OPT_BOOL(0, "allow-empty", &opts->allow_empty, N_("preserve initially empty commits")),
OPT_BOOL(0, "allow-empty-message", &opts->allow_empty_message, N_("allow commits with empty messages")),
OPT_BOOL(0, "keep-redundant-commits", &opts->keep_redundant_commits, N_("keep redundant, empty commits")),
- OPT_BOOL(0, "skip-empty", &opts->skip_empty, N_("skip redundant, empty commits")),
+ OPT_BOOL(0, "skip-empty", &opts->skip_empty, N_("skip both redundant and initially empty commits")),
+ OPT_BOOL(0, "skip-redundant-commits", &opts->skip_redundant_commits, N_("skip redundant commits")),
OPT_END(),
};
options = parse_options_concat(options, cp_extra);
@@ -115,6 +116,9 @@ static int run_sequencer(int argc, const char **argv, struct replay_opts *opts)
/* implies allow_empty */
if (opts->keep_redundant_commits)
opts->allow_empty = 1;
+ /* implies skip_redundant_commits */
+ if (opts->skip_empty)
+ opts->skip_redundant_commits = 1;
/* Check for incompatible command line arguments */
if (cmd) {
@@ -147,6 +151,18 @@ static int run_sequencer(int argc, const char **argv, struct replay_opts *opts)
"--edit", opts->edit,
NULL);
+ if (opts->keep_redundant_commits)
+ verify_opt_compatible(me, "--keep-redundant-commits",
+ "--skip-empty", opts->skip_empty,
+ "--skip-redundant-commits", opts->skip_redundant_commits,
+ NULL);
+
+ if (opts->keep_redundant_commits)
+ verify_opt_compatible(me, "--skip-empty",
+ "--allow-empty", opts->allow_empty,
+ "--keep-redundant-commits", opts->keep_redundant_commits,
+ NULL);
+
if (cmd) {
opts->revs = NULL;
} else {
diff --git a/sequencer.c b/sequencer.c
index 9c01310162..333d9112de 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -563,40 +563,70 @@ static int allow_or_skip_empty(struct replay_opts *opts, struct commit *commit)
{
int index_unchanged, empty_commit;
- /*
- * Four cases:
+ /* We have four options:
*
- * (1) we do not allow empty at all and error out;
+ * --allow-empty (AE)
+ * --keep-redundant-commits (KR)
+ * --skip-empty (SE)
+ * --skip-redundant-commits (SR)
*
- * (2) we skip empty commits altogether;
+ * Additionally, if KR, then AE. And if SE, then SR.
+ *
+ * We have three possible states:
+ * Not Empty (NE)
+ * Originally Empty (OE)
+ * made REdundant (RE) (originally not empty)
*
- * (3) we allow ones that were initially empty, but
- * forbid the ones that become empty;
+ * NE always gets committed. The other two depend on the combination
+ * of flags.
*
- * (4) we allow both.
+ * OE outcome | RE outcome | AE KR SE SR
+ * Case 0: 0 (error) 0 (error) 0 0 0 0
+ * Case 1: 1 (allow) 0 (error) 1 0 0 0
+ * N/A Case 2: 2 (skip) 0 (error) 0 0 1 0
+ * N/A Case 3: 0 (error) 1 (keep) 0 1 0 0
+ * Case 4: 1 (allow) 1 (keep) 1 1 0 0
+ * N/A Case 5: 2 (skip) 1 (keep) 0 1 1 0
+ * Case 6: 0 (error) 2 (skip) 0 0 0 1
+ * Case 7: 1 (allow) 2 (skip) 1 0 0 1
+ * Case 8: 2 (skip ) 2 (skip) 0 0 1 1
+ *
+ * TODO should we allow Case 2? If so, how?
*/
- if (!opts->allow_empty && !opts->skip_empty)
+
+ /* Case 0 */
+ if (!opts->allow_empty && !opts->skip_redundant_commits)
return 0; /* let "git commit" barf as necessary */
index_unchanged = is_index_unchanged();
if (index_unchanged < 0)
return index_unchanged;
+
if (!index_unchanged)
return 0; /* we do not have to say --allow-empty */
- if (opts->skip_empty)
- return 2;
+ /* Here we know that the commit is either OE or RE */
+ /* Case 4, we don't care, result is 'allow' for both cases */
if (opts->keep_redundant_commits)
return 1;
+ /* Case 8, we don't care, result is 'skip' for both cases */
+ if (opts->skip_empty)
+ return 2;
+
+ /* Now we must differentiate between OE and RE,
+ * for Case 1, 6, 7 */
empty_commit = is_original_commit_empty(commit);
if (empty_commit < 0)
return empty_commit;
- if (!empty_commit)
- return 0;
- else
- return 1;
+
+ /* An OE will return 1 if AE, 0 otherwise */
+ if (empty_commit)
+ return opts->allow_empty;
+
+ /* An RE will return 2 if SR, 0 otherwise */
+ return 2*opts->skip_redundant_commits;
}
enum todo_command {
@@ -1009,6 +1039,8 @@ static int populate_opts_cb(const char *key, const char *value, void *data)
opts->keep_redundant_commits = git_config_bool_or_int(key, value, &error_flag);
else if (!strcmp(key, "options.skip-empty"))
opts->skip_empty = git_config_bool_or_int(key, value, &error_flag);
+ else if (!strcmp(key, "options.skip-redundant-commits"))
+ opts->skip_redundant_commits = git_config_bool_or_int(key, value, &error_flag);
else if (!strcmp(key, "options.mainline"))
opts->mainline = git_config_int(key, value);
else if (!strcmp(key, "options.gpg-sign"))
@@ -1267,6 +1299,8 @@ static int save_opts(struct replay_opts *opts)
res |= git_config_set_in_file_gently(opts_file, "options.keep-redundant-commits", "true");
if (opts->skip_empty)
res |= git_config_set_in_file_gently(opts_file, "options.skip-empty", "true");
+ if (opts->skip_redundant_commits)
+ res |= git_config_set_in_file_gently(opts_file, "options.skip-redundant-commits", "true");
if (opts->mainline) {
struct strbuf buf = STRBUF_INIT;
strbuf_addf(&buf, "%d", opts->mainline);
diff --git a/sequencer.h b/sequencer.h
index c747cfcfc7..f8b8bd0063 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -24,6 +24,7 @@ struct replay_opts {
int allow_empty_message;
int keep_redundant_commits;
int skip_empty;
+ int skip_redundant_commits;;
int mainline;
--
2.11.0.616.gd72966cf44.dirty
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 5/5] sequencer: allow to --skip current commit
2017-01-23 22:52 [PATCH 0/5] sequencer: allow skipping commits Giuseppe Bilotta
` (3 preceding siblings ...)
2017-01-23 22:52 ` [PATCH 4/5] cherry-pick: allow skipping only redundant commits Giuseppe Bilotta
@ 2017-01-23 22:52 ` Giuseppe Bilotta
4 siblings, 0 replies; 6+ messages in thread
From: Giuseppe Bilotta @ 2017-01-23 22:52 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Giuseppe Bilotta
If a sequencing gets interrupted (by a conflict or an empty commit or
whatever), the user can now opt to just skip it passing the `--skip`
command line option, which acts like a `--continue`, except that the
current commit gets skipped.
Signed-off-by: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>
---
Documentation/sequencer.txt | 10 +++++++++-
builtin/revert.c | 7 +++++--
sequencer.c | 32 ++++++++++++++++++++++++++++----
sequencer.h | 2 +-
4 files changed, 43 insertions(+), 8 deletions(-)
diff --git a/Documentation/sequencer.txt b/Documentation/sequencer.txt
index 5747f442f2..095d6cd732 100644
--- a/Documentation/sequencer.txt
+++ b/Documentation/sequencer.txt
@@ -1,7 +1,15 @@
--continue::
Continue the operation in progress using the information in
'.git/sequencer'. Can be used to continue after resolving
- conflicts in a failed cherry-pick or revert.
+ conflicts in a failed cherry-pick or revert. Use `--skip`
+ instead if the current commit should be ignored.
+
+--skip::
+ Skips the current commit, and then continues the operation
+ in progress using the information in '.git/sequencer'.i
+ Can be used to continue to a cherry-pick or rever that was
+ interrupted by an empty commit, or by a commit that conflicts
+ and for which the resolution is to discard the commit.
--quit::
Forget about the current operation in progress. Can be used
diff --git a/builtin/revert.c b/builtin/revert.c
index aca8a1d9d0..dece0bebf7 100644
--- a/builtin/revert.c
+++ b/builtin/revert.c
@@ -79,6 +79,7 @@ static int run_sequencer(int argc, const char **argv, struct replay_opts *opts)
struct option base_options[] = {
OPT_CMDMODE(0, "quit", &cmd, N_("end revert or cherry-pick sequence"), 'q'),
OPT_CMDMODE(0, "continue", &cmd, N_("resume revert or cherry-pick sequence"), 'c'),
+ OPT_CMDMODE(0, "skip", &cmd, N_("resume revert or cherry-pick sequence, skipping this commit"), 's'),
OPT_CMDMODE(0, "abort", &cmd, N_("cancel revert or cherry-pick sequence"), 'a'),
OPT_BOOL('n', "no-commit", &opts->no_commit, N_("don't automatically commit")),
OPT_BOOL('e', "edit", &opts->edit, N_("edit the commit message")),
@@ -127,6 +128,8 @@ static int run_sequencer(int argc, const char **argv, struct replay_opts *opts)
this_operation = "--quit";
else if (cmd == 'c')
this_operation = "--continue";
+ else if (cmd == 's')
+ this_operation = "--skip";
else {
assert(cmd == 'a');
this_operation = "--abort";
@@ -188,8 +191,8 @@ static int run_sequencer(int argc, const char **argv, struct replay_opts *opts)
if (cmd == 'q')
return sequencer_remove_state(opts);
- if (cmd == 'c')
- return sequencer_continue(opts);
+ if (cmd == 'c' || cmd == 's')
+ return sequencer_continue(opts, cmd);
if (cmd == 'a')
return sequencer_rollback(opts);
return sequencer_pick_revisions(opts);
diff --git a/sequencer.c b/sequencer.c
index 333d9112de..cfe8c06989 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -1359,21 +1359,45 @@ static int continue_single_pick(void)
return run_command_v_opt(argv, RUN_GIT_CMD);
}
-int sequencer_continue(struct replay_opts *opts)
+/*
+ * Continue the sequencing, after either committing
+ * (cmd == 'c') or skipping (cmd == 's') the current
+ * commit.
+ */
+int sequencer_continue(struct replay_opts *opts, char cmd)
{
struct todo_list todo_list = TODO_LIST_INIT;
- int res;
+ int single, res;
if (read_and_refresh_cache(opts))
return -1;
- if (!file_exists(get_todo_path(opts)))
- return continue_single_pick();
+ if (!file_exists(get_todo_path(opts))) {
+ if (cmd == 'c') {
+ return continue_single_pick();
+ } else {
+ assert(cmd == 's');
+ /* Skipping the only commit is equivalent to an abort */
+ return sequencer_rollback(opts);
+ }
+ }
if (read_populate_opts(opts))
return -1;
if ((res = read_populate_todo(&todo_list, opts)))
goto release_todo_list;
+ /* If we were asked to skip this commit, rollback
+ * and continue with the next */
+ if (cmd == 's') {
+ if ((res = rollback_single_pick()))
+ goto release_todo_list;
+ discard_cache();
+ if ((res = read_cache()) < 0)
+ goto release_todo_list;
+ printf("index unchanged: %d\n", is_index_unchanged());
+ goto skip_this_commit;
+ }
+
/* check if there is something to commit */
res = is_index_unchanged();
if (res < 0)
diff --git a/sequencer.h b/sequencer.h
index f8b8bd0063..afc4bb4e6c 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -41,7 +41,7 @@ struct replay_opts {
#define REPLAY_OPTS_INIT { -1 }
int sequencer_pick_revisions(struct replay_opts *opts);
-int sequencer_continue(struct replay_opts *opts);
+int sequencer_continue(struct replay_opts *opts, char cmd);
int sequencer_rollback(struct replay_opts *opts);
int sequencer_remove_state(struct replay_opts *opts);
--
2.11.0.616.gd72966cf44.dirty
^ permalink raw reply related [flat|nested] 6+ messages in thread