Re: [PATCH v2 00/12] add --ff option to cherry-pick
From: Junio C Hamano <hidden>
Date: 2016-06-15 22:48:23
Subsystem:
the rest · Maintainer:
Linus Torvalds
Possibly related (same subject, not in this thread)
- 2016-06-15 · Re: [PATCH v2 00/12] add --ff option to cherry-pick · Christian Couder <hidden>
- 2016-06-15 · Re: [PATCH v2 00/12] add --ff option to cherry-pick · Junio C Hamano <hidden>
- 2016-06-15 · [PATCH v2 00/12] add --ff option to cherry-pick · Christian Couder <hidden>
- 2016-06-15 · Re: [PATCH v2 00/12] add --ff option to cherry-pick · Junio C Hamano <hidden>
- 2016-06-15 · Re: [PATCH v2 00/12] add --ff option to cherry-pick · Daniel Barkalow <hidden>
Christian Couder [off-list ref] writes:
I tried to use the checkout_fast_forward() function from builtin/merge.c but unfortunately it doesn't work. It gives an error like that in the tests : error: Your local changes to 'file1' would be overwritten by merge. Aborting. Please, commit your changes or stash them before you can merge. and I don't really understand why. (Though I didn't spend a lot of time on this.)
Shouldn't it be something like this? The patch is still unnecessarily large because I wanted to share options between revert and cherry-pick while giving --ff only to cherry-pick, but I don't understand why it needs a nine patch series worth of code churn. builtin-merge.c | 2 +- builtin-revert.c | 44 +++++++++++++++++++++++++++++++++++++++++--- cache.h | 3 +++ parse-options.c | 15 +++++++++++++++ parse-options.h | 1 + 5 files changed, 61 insertions(+), 4 deletions(-)
diff --git a/builtin-merge.c b/builtin-merge.c
index 3aaec7b..c043066 100644
--- a/builtin-merge.c
+++ b/builtin-merge.c@@ -667,7 +667,7 @@ static int count_unmerged_entries(void) return ret; } -static int checkout_fast_forward(unsigned char *head, unsigned char *remote) +int checkout_fast_forward(const unsigned char *head, const unsigned char *remote) { struct tree *trees[MAX_UNPACK_TREES]; struct unpack_trees_options opts;
diff --git a/builtin-revert.c b/builtin-revert.c
index eff5268..bfe75c8 100644
--- a/builtin-revert.c
+++ b/builtin-revert.c@@ -13,6 +13,7 @@ #include "revision.h" #include "rerere.h" #include "merge-recursive.h" +#include "refs.h" /* * This implements the builtins revert and cherry-pick.
@@ -35,7 +36,7 @@ static const char * const cherry_pick_usage[] = { NULL }; -static int edit, no_replay, no_commit, mainline, signoff; +static int edit, no_replay, no_commit, mainline, signoff, allow_ff; static enum { REVERT, CHERRY_PICK } action; static struct commit *commit; static const char *commit_name;
@@ -60,8 +61,19 @@ static void parse_args(int argc, const char **argv) OPT_INTEGER('m', "mainline", &mainline, "parent number"), OPT_RERERE_AUTOUPDATE(&allow_rerere_auto), OPT_END(), + OPT_END(), + OPT_END(), }; + if (action == CHERRY_PICK) { + struct option cp_extra[] = { + OPT_BOOLEAN(0, "ff", &allow_ff, "allow fast-forward"), + OPT_END(), + }; + if (parse_options_concat(options, ARRAY_SIZE(options), cp_extra)) + die("program error"); + } + if (parse_options(argc, argv, NULL, options, usage_str, 0) != 1) usage_with_options(usage_str, options);
@@ -244,6 +256,17 @@ static NORETURN void die_dirty_index(const char *me) } } +static int fast_forward_to(const unsigned char *to, const unsigned char *from) +{ + struct ref_lock *ref_lock; + + read_cache(); + if (checkout_fast_forward(from, to)) + exit(1); /* the callee should have complained already */ + ref_lock = lock_any_ref_for_update("HEAD", from, 0); + return write_ref_sha1(ref_lock, to, "cherry-pick"); +} + static int revert_or_cherry_pick(int argc, const char **argv) { unsigned char head[20];
@@ -265,6 +288,17 @@ static int revert_or_cherry_pick(int argc, const char **argv) if (action == REVERT && !no_replay) die("revert is incompatible with replay"); + if (action == CHERRY_PICK && allow_ff) { + if (signoff) + die("cherry-pick --ff cannot be used with --signoff"); + if (no_commit) + die("cherry-pick --ff cannot be used with --no-commit"); + if (no_replay) + die("cherry-pick --ff cannot be used with -x"); + if (edit) + die("cherry-pick --ff cannot be used with --edit"); + } + if (read_cache() < 0) die("git %s: failed to read the index", me); if (no_commit) {
@@ -284,8 +318,6 @@ static int revert_or_cherry_pick(int argc, const char **argv) } discard_cache(); - index_fd = hold_locked_index(&index_lock, 1); - if (!commit->parents) { if (action == REVERT) die ("Cannot revert a root commit");
@@ -314,6 +346,10 @@ static int revert_or_cherry_pick(int argc, const char **argv) else parent = commit->parents->item; + if (action == CHERRY_PICK && allow_ff + && !hashcmp(parent->object.sha1, head)) + return fast_forward_to(commit->object.sha1, head); + if (!(message = commit->buffer)) die ("Cannot get commit message for %s", sha1_to_hex(commit->object.sha1));
@@ -343,6 +379,8 @@ static int revert_or_cherry_pick(int argc, const char **argv) oneline = get_oneline(message); + index_fd = hold_locked_index(&index_lock, 1); + if (action == REVERT) { char *oneline_body = strchr(oneline, ' ');
diff --git a/cache.h b/cache.h
index d454b7e..7272160 100644
--- a/cache.h
+++ b/cache.h@@ -1040,4 +1040,7 @@ void overlay_tree_on_cache(const char *tree_name, const char *prefix); char *alias_lookup(const char *alias); int split_cmdline(char *cmdline, const char ***argv); +/* builtin-merge.c */ +int checkout_fast_forward(const unsigned char *from, const unsigned char *to); + #endif /* CACHE_H */
diff --git a/parse-options.c b/parse-options.c
index c83035d..8546d85 100644
--- a/parse-options.c
+++ b/parse-options.c@@ -659,3 +659,18 @@ int parse_opt_tertiary(const struct option *opt, const char *arg, int unset) *target = unset ? 2 : 1; return 0; } + +int parse_options_concat(struct option *dst, size_t dst_size, struct option *src) +{ + int i, j; + + for (i = 0; i < dst_size; i++) + if (dst[i].type == OPTION_END) + break; + for (j = 0; i < dst_size; i++, j++) { + dst[i] = src[j]; + if (src[j].type == OPTION_END) + return 0; + } + return -1; +}
diff --git a/parse-options.h b/parse-options.h
index 9429f7e..7581e93 100644
--- a/parse-options.h
+++ b/parse-options.h@@ -187,6 +187,7 @@ extern int parse_options_step(struct parse_opt_ctx_t *ctx, extern int parse_options_end(struct parse_opt_ctx_t *ctx); +extern int parse_options_concat(struct option *dst, size_t, struct option *src); /*----- some often used options -----*/ extern int parse_opt_abbrev_cb(const struct option *, const char *, int);