Skip to content

Commit c62f6ec

Browse files
committed
revert: add --ff option to allow fast forward when cherry-picking
As "git merge" fast forwards if possible, it seems sensible to have such a feature for "git cherry-pick" too, especially as it could be used in git-rebase--interactive.sh. Maybe this option could be made the default in the long run, with another --no-ff option to disable this default behavior, but that could make some scripts backward incompatible and/or that would require testing if some GIT_AUTHOR_* environment variables are set. So we don't do that for now. Signed-off-by: Christian Couder <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent cac42b2 commit c62f6ec

File tree

1 file changed

+40
-3
lines changed

1 file changed

+40
-3
lines changed

builtin-revert.c

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "revision.h"
1414
#include "rerere.h"
1515
#include "merge-recursive.h"
16+
#include "refs.h"
1617

1718
/*
1819
* This implements the builtins revert and cherry-pick.
@@ -35,7 +36,7 @@ static const char * const cherry_pick_usage[] = {
3536
NULL
3637
};
3738

38-
static int edit, no_replay, no_commit, mainline, signoff;
39+
static int edit, no_replay, no_commit, mainline, signoff, allow_ff;
3940
static enum { REVERT, CHERRY_PICK } action;
4041
static struct commit *commit;
4142
static const char *commit_name;
@@ -60,8 +61,19 @@ static void parse_args(int argc, const char **argv)
6061
OPT_INTEGER('m', "mainline", &mainline, "parent number"),
6162
OPT_RERERE_AUTOUPDATE(&allow_rerere_auto),
6263
OPT_END(),
64+
OPT_END(),
65+
OPT_END(),
6366
};
6467

68+
if (action == CHERRY_PICK) {
69+
struct option cp_extra[] = {
70+
OPT_BOOLEAN(0, "ff", &allow_ff, "allow fast-forward"),
71+
OPT_END(),
72+
};
73+
if (parse_options_concat(options, ARRAY_SIZE(options), cp_extra))
74+
die("program error");
75+
}
76+
6577
if (parse_options(argc, argv, NULL, options, usage_str, 0) != 1)
6678
usage_with_options(usage_str, options);
6779

@@ -244,6 +256,17 @@ static NORETURN void die_dirty_index(const char *me)
244256
}
245257
}
246258

259+
static int fast_forward_to(const unsigned char *to, const unsigned char *from)
260+
{
261+
struct ref_lock *ref_lock;
262+
263+
read_cache();
264+
if (checkout_fast_forward(from, to))
265+
exit(1); /* the callee should have complained already */
266+
ref_lock = lock_any_ref_for_update("HEAD", from, 0);
267+
return write_ref_sha1(ref_lock, to, "cherry-pick");
268+
}
269+
247270
static int revert_or_cherry_pick(int argc, const char **argv)
248271
{
249272
unsigned char head[20];
@@ -265,6 +288,17 @@ static int revert_or_cherry_pick(int argc, const char **argv)
265288
if (action == REVERT && !no_replay)
266289
die("revert is incompatible with replay");
267290

291+
if (allow_ff) {
292+
if (signoff)
293+
die("cherry-pick --ff cannot be used with --signoff");
294+
if (no_commit)
295+
die("cherry-pick --ff cannot be used with --no-commit");
296+
if (no_replay)
297+
die("cherry-pick --ff cannot be used with -x");
298+
if (edit)
299+
die("cherry-pick --ff cannot be used with --edit");
300+
}
301+
268302
if (read_cache() < 0)
269303
die("git %s: failed to read the index", me);
270304
if (no_commit) {
@@ -284,8 +318,6 @@ static int revert_or_cherry_pick(int argc, const char **argv)
284318
}
285319
discard_cache();
286320

287-
index_fd = hold_locked_index(&index_lock, 1);
288-
289321
if (!commit->parents) {
290322
if (action == REVERT)
291323
die ("Cannot revert a root commit");
@@ -314,6 +346,9 @@ static int revert_or_cherry_pick(int argc, const char **argv)
314346
else
315347
parent = commit->parents->item;
316348

349+
if (allow_ff && !hashcmp(parent->object.sha1, head))
350+
return fast_forward_to(commit->object.sha1, head);
351+
317352
if (!(message = commit->buffer))
318353
die ("Cannot get commit message for %s",
319354
sha1_to_hex(commit->object.sha1));
@@ -343,6 +378,8 @@ static int revert_or_cherry_pick(int argc, const char **argv)
343378

344379
oneline = get_oneline(message);
345380

381+
index_fd = hold_locked_index(&index_lock, 1);
382+
346383
if (action == REVERT) {
347384
char *oneline_body = strchr(oneline, ' ');
348385

0 commit comments

Comments
 (0)