Teach --[no-]rerere-autoupdate option to merge, revert and friends
Introduce a command line option to override rerere.autoupdate configuration variable to make it more useful. Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
1a56be134f
commit
cb6020bb01
@ -10,7 +10,7 @@ SYNOPSIS
|
|||||||
--------
|
--------
|
||||||
[verse]
|
[verse]
|
||||||
'git merge' [-n] [--stat] [--no-commit] [--squash] [-s <strategy>]...
|
'git merge' [-n] [--stat] [--no-commit] [--squash] [-s <strategy>]...
|
||||||
[-m <msg>] <remote>...
|
[--[no-]rerere-autoupdate] [-m <msg>] <remote>...
|
||||||
'git merge' <msg> HEAD <remote>...
|
'git merge' <msg> HEAD <remote>...
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
@ -33,6 +33,11 @@ include::merge-options.txt[]
|
|||||||
used to give a good default for automated 'git merge'
|
used to give a good default for automated 'git merge'
|
||||||
invocations.
|
invocations.
|
||||||
|
|
||||||
|
--rerere-autoupdate::
|
||||||
|
--no-rerere-autoupdate::
|
||||||
|
Allow the rerere mechanism to update the index with the
|
||||||
|
result of auto-conflict resolution if possible.
|
||||||
|
|
||||||
<remote>...::
|
<remote>...::
|
||||||
Other branch heads to merge into our branch. You need at
|
Other branch heads to merge into our branch. You need at
|
||||||
least one <remote>. Specifying more than one <remote>
|
least one <remote>. Specifying more than one <remote>
|
||||||
|
@ -1150,7 +1150,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
|
|||||||
"new_index file. Check that disk is not full or quota is\n"
|
"new_index file. Check that disk is not full or quota is\n"
|
||||||
"not exceeded, and then \"git reset HEAD\" to recover.");
|
"not exceeded, and then \"git reset HEAD\" to recover.");
|
||||||
|
|
||||||
rerere();
|
rerere(0);
|
||||||
run_hook(get_index_file(), "post-commit", NULL);
|
run_hook(get_index_file(), "post-commit", NULL);
|
||||||
if (!quiet)
|
if (!quiet)
|
||||||
print_summary(prefix, commit_sha1);
|
print_summary(prefix, commit_sha1);
|
||||||
|
@ -52,6 +52,7 @@ static struct strategy **use_strategies;
|
|||||||
static size_t use_strategies_nr, use_strategies_alloc;
|
static size_t use_strategies_nr, use_strategies_alloc;
|
||||||
static const char *branch;
|
static const char *branch;
|
||||||
static int verbosity;
|
static int verbosity;
|
||||||
|
static int allow_rerere_auto;
|
||||||
|
|
||||||
static struct strategy all_strategy[] = {
|
static struct strategy all_strategy[] = {
|
||||||
{ "recursive", DEFAULT_TWOHEAD | NO_TRIVIAL },
|
{ "recursive", DEFAULT_TWOHEAD | NO_TRIVIAL },
|
||||||
@ -170,6 +171,7 @@ static struct option builtin_merge_options[] = {
|
|||||||
"allow fast-forward (default)"),
|
"allow fast-forward (default)"),
|
||||||
OPT_BOOLEAN(0, "ff-only", &fast_forward_only,
|
OPT_BOOLEAN(0, "ff-only", &fast_forward_only,
|
||||||
"abort if fast-forward is not possible"),
|
"abort if fast-forward is not possible"),
|
||||||
|
OPT_RERERE_AUTOUPDATE(&allow_rerere_auto),
|
||||||
OPT_CALLBACK('s', "strategy", &use_strategies, "strategy",
|
OPT_CALLBACK('s', "strategy", &use_strategies, "strategy",
|
||||||
"merge strategy to use", option_parse_strategy),
|
"merge strategy to use", option_parse_strategy),
|
||||||
OPT_CALLBACK('m', "message", &merge_msg, "message",
|
OPT_CALLBACK('m', "message", &merge_msg, "message",
|
||||||
@ -790,7 +792,7 @@ static int suggest_conflicts(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
rerere();
|
rerere(allow_rerere_auto);
|
||||||
printf("Automatic merge failed; "
|
printf("Automatic merge failed; "
|
||||||
"fix conflicts and then commit the result.\n");
|
"fix conflicts and then commit the result.\n");
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -101,15 +101,24 @@ static int diff_two(const char *file1, const char *label1,
|
|||||||
int cmd_rerere(int argc, const char **argv, const char *prefix)
|
int cmd_rerere(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
struct string_list merge_rr = { NULL, 0, 0, 1 };
|
struct string_list merge_rr = { NULL, 0, 0, 1 };
|
||||||
int i, fd;
|
int i, fd, flags = 0;
|
||||||
|
|
||||||
|
if (2 < argc) {
|
||||||
|
if (!strcmp(argv[1], "-h"))
|
||||||
|
usage(git_rerere_usage);
|
||||||
|
if (!strcmp(argv[1], "--rerere-autoupdate"))
|
||||||
|
flags = RERERE_AUTOUPDATE;
|
||||||
|
else if (!strcmp(argv[1], "--no-rerere-autoupdate"))
|
||||||
|
flags = RERERE_NOAUTOUPDATE;
|
||||||
|
if (flags) {
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (argc < 2)
|
if (argc < 2)
|
||||||
return rerere();
|
return rerere(flags);
|
||||||
|
|
||||||
if (!strcmp(argv[1], "-h"))
|
fd = setup_rerere(&merge_rr, flags);
|
||||||
usage(git_rerere_usage);
|
|
||||||
|
|
||||||
fd = setup_rerere(&merge_rr);
|
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@ static const char * const cherry_pick_usage[] = {
|
|||||||
static int edit, no_replay, no_commit, mainline, signoff;
|
static int edit, no_replay, no_commit, mainline, signoff;
|
||||||
static enum { REVERT, CHERRY_PICK } action;
|
static enum { REVERT, CHERRY_PICK } action;
|
||||||
static struct commit *commit;
|
static struct commit *commit;
|
||||||
|
static int allow_rerere_auto;
|
||||||
|
|
||||||
static const char *me;
|
static const char *me;
|
||||||
|
|
||||||
@ -57,6 +58,7 @@ static void parse_args(int argc, const char **argv)
|
|||||||
OPT_BOOLEAN('r', NULL, &noop, "no-op (backward compatibility)"),
|
OPT_BOOLEAN('r', NULL, &noop, "no-op (backward compatibility)"),
|
||||||
OPT_BOOLEAN('s', "signoff", &signoff, "add Signed-off-by:"),
|
OPT_BOOLEAN('s', "signoff", &signoff, "add Signed-off-by:"),
|
||||||
OPT_INTEGER('m', "mainline", &mainline, "parent number"),
|
OPT_INTEGER('m', "mainline", &mainline, "parent number"),
|
||||||
|
OPT_RERERE_AUTOUPDATE(&allow_rerere_auto),
|
||||||
OPT_END(),
|
OPT_END(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -395,7 +397,7 @@ static int revert_or_cherry_pick(int argc, const char **argv)
|
|||||||
die ("Error wrapping up %s", defmsg);
|
die ("Error wrapping up %s", defmsg);
|
||||||
fprintf(stderr, "Automatic %s failed.%s\n",
|
fprintf(stderr, "Automatic %s failed.%s\n",
|
||||||
me, help_msg(commit->object.sha1));
|
me, help_msg(commit->object.sha1));
|
||||||
rerere();
|
rerere(allow_rerere_auto);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if (commit_lock_file(&msg_file) < 0)
|
if (commit_lock_file(&msg_file) < 0)
|
||||||
|
@ -30,6 +30,7 @@ skip skip the current patch
|
|||||||
abort restore the original branch and abort the patching operation.
|
abort restore the original branch and abort the patching operation.
|
||||||
committer-date-is-author-date lie about committer date
|
committer-date-is-author-date lie about committer date
|
||||||
ignore-date use current timestamp for author date
|
ignore-date use current timestamp for author date
|
||||||
|
rerere-autoupdate update the index with reused conflict resolution if possible
|
||||||
rebasing* (internal use for git-rebase)"
|
rebasing* (internal use for git-rebase)"
|
||||||
|
|
||||||
. git-sh-setup
|
. git-sh-setup
|
||||||
@ -135,7 +136,7 @@ It does not apply to blobs recorded in its index."
|
|||||||
export GIT_MERGE_VERBOSITY=0
|
export GIT_MERGE_VERBOSITY=0
|
||||||
fi
|
fi
|
||||||
git-merge-recursive $orig_tree -- HEAD $his_tree || {
|
git-merge-recursive $orig_tree -- HEAD $his_tree || {
|
||||||
git rerere
|
git rerere $allow_rerere_autoupdate
|
||||||
echo Failed to merge in the changes.
|
echo Failed to merge in the changes.
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
@ -293,6 +294,7 @@ resolvemsg= resume= scissors= no_inbody_headers=
|
|||||||
git_apply_opt=
|
git_apply_opt=
|
||||||
committer_date_is_author_date=
|
committer_date_is_author_date=
|
||||||
ignore_date=
|
ignore_date=
|
||||||
|
allow_rerere_autoupdate=
|
||||||
|
|
||||||
while test $# != 0
|
while test $# != 0
|
||||||
do
|
do
|
||||||
@ -340,6 +342,8 @@ do
|
|||||||
committer_date_is_author_date=t ;;
|
committer_date_is_author_date=t ;;
|
||||||
--ignore-date)
|
--ignore-date)
|
||||||
ignore_date=t ;;
|
ignore_date=t ;;
|
||||||
|
--rerere-autoupdate|--no-rerere-autoupdate)
|
||||||
|
allow_rerere_autoupdate="$1" ;;
|
||||||
-q|--quiet)
|
-q|--quiet)
|
||||||
GIT_QUIET=t ;;
|
GIT_QUIET=t ;;
|
||||||
--)
|
--)
|
||||||
|
@ -50,6 +50,7 @@ diffstat=$(git config --bool rebase.stat)
|
|||||||
git_am_opt=
|
git_am_opt=
|
||||||
rebase_root=
|
rebase_root=
|
||||||
force_rebase=
|
force_rebase=
|
||||||
|
allow_rerere_autoupdate=
|
||||||
|
|
||||||
continue_merge () {
|
continue_merge () {
|
||||||
test -n "$prev_head" || die "prev_head must be defined"
|
test -n "$prev_head" || die "prev_head must be defined"
|
||||||
@ -118,7 +119,7 @@ call_merge () {
|
|||||||
return
|
return
|
||||||
;;
|
;;
|
||||||
1)
|
1)
|
||||||
git rerere
|
git rerere $allow_rerere_autoupdate
|
||||||
die "$RESOLVEMSG"
|
die "$RESOLVEMSG"
|
||||||
;;
|
;;
|
||||||
2)
|
2)
|
||||||
@ -349,6 +350,9 @@ do
|
|||||||
-f|--f|--fo|--for|--forc|force|--force-r|--force-re|--force-reb|--force-reba|--force-rebas|--force-rebase)
|
-f|--f|--fo|--for|--forc|force|--force-r|--force-re|--force-reb|--force-reba|--force-rebas|--force-rebase)
|
||||||
force_rebase=t
|
force_rebase=t
|
||||||
;;
|
;;
|
||||||
|
--rerere-autoupdate|--no-rerere-autoupdate)
|
||||||
|
allow_rerere_autoupdate="$1"
|
||||||
|
;;
|
||||||
-*)
|
-*)
|
||||||
usage
|
usage
|
||||||
;;
|
;;
|
||||||
|
@ -633,3 +633,10 @@ int parse_opt_with_commit(const struct option *opt, const char *arg, int unset)
|
|||||||
commit_list_insert(commit, opt->value);
|
commit_list_insert(commit, opt->value);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int parse_opt_tertiary(const struct option *opt, const char *arg, int unset)
|
||||||
|
{
|
||||||
|
int *target = opt->value;
|
||||||
|
*target = unset ? 2 : 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -123,6 +123,8 @@ struct option {
|
|||||||
(h), PARSE_OPT_NOARG, NULL, (p) }
|
(h), PARSE_OPT_NOARG, NULL, (p) }
|
||||||
#define OPT_INTEGER(s, l, v, h) { OPTION_INTEGER, (s), (l), (v), "n", (h) }
|
#define OPT_INTEGER(s, l, v, h) { OPTION_INTEGER, (s), (l), (v), "n", (h) }
|
||||||
#define OPT_STRING(s, l, v, a, h) { OPTION_STRING, (s), (l), (v), (a), (h) }
|
#define OPT_STRING(s, l, v, a, h) { OPTION_STRING, (s), (l), (v), (a), (h) }
|
||||||
|
#define OPT_UYN(s, l, v, h) { OPTION_CALLBACK, (s), (l), (v), NULL, \
|
||||||
|
(h), PARSE_OPT_NOARG, &parse_opt_tertiary }
|
||||||
#define OPT_DATE(s, l, v, h) \
|
#define OPT_DATE(s, l, v, h) \
|
||||||
{ OPTION_CALLBACK, (s), (l), (v), "time",(h), 0, \
|
{ OPTION_CALLBACK, (s), (l), (v), "time",(h), 0, \
|
||||||
parse_opt_approxidate_cb }
|
parse_opt_approxidate_cb }
|
||||||
@ -190,6 +192,7 @@ extern int parse_opt_abbrev_cb(const struct option *, const char *, int);
|
|||||||
extern int parse_opt_approxidate_cb(const struct option *, const char *, int);
|
extern int parse_opt_approxidate_cb(const struct option *, const char *, int);
|
||||||
extern int parse_opt_verbosity_cb(const struct option *, const char *, int);
|
extern int parse_opt_verbosity_cb(const struct option *, const char *, int);
|
||||||
extern int parse_opt_with_commit(const struct option *, const char *, int);
|
extern int parse_opt_with_commit(const struct option *, const char *, int);
|
||||||
|
extern int parse_opt_tertiary(const struct option *, const char *, int);
|
||||||
|
|
||||||
#define OPT__VERBOSE(var) OPT_BOOLEAN('v', "verbose", (var), "be verbose")
|
#define OPT__VERBOSE(var) OPT_BOOLEAN('v', "verbose", (var), "be verbose")
|
||||||
#define OPT__QUIET(var) OPT_BOOLEAN('q', "quiet", (var), "be quiet")
|
#define OPT__QUIET(var) OPT_BOOLEAN('q', "quiet", (var), "be quiet")
|
||||||
|
8
rerere.c
8
rerere.c
@ -367,7 +367,7 @@ static int is_rerere_enabled(void)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int setup_rerere(struct string_list *merge_rr)
|
int setup_rerere(struct string_list *merge_rr, int flags)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
@ -375,6 +375,8 @@ int setup_rerere(struct string_list *merge_rr)
|
|||||||
if (!is_rerere_enabled())
|
if (!is_rerere_enabled())
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (flags & (RERERE_AUTOUPDATE|RERERE_NOAUTOUPDATE))
|
||||||
|
rerere_autoupdate = !!(flags & RERERE_AUTOUPDATE);
|
||||||
merge_rr_path = git_pathdup("MERGE_RR");
|
merge_rr_path = git_pathdup("MERGE_RR");
|
||||||
fd = hold_lock_file_for_update(&write_lock, merge_rr_path,
|
fd = hold_lock_file_for_update(&write_lock, merge_rr_path,
|
||||||
LOCK_DIE_ON_ERROR);
|
LOCK_DIE_ON_ERROR);
|
||||||
@ -382,12 +384,12 @@ int setup_rerere(struct string_list *merge_rr)
|
|||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rerere(void)
|
int rerere(int flags)
|
||||||
{
|
{
|
||||||
struct string_list merge_rr = { NULL, 0, 0, 1 };
|
struct string_list merge_rr = { NULL, 0, 0, 1 };
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
fd = setup_rerere(&merge_rr);
|
fd = setup_rerere(&merge_rr, flags);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return 0;
|
return 0;
|
||||||
return do_plain_rerere(&merge_rr, fd);
|
return do_plain_rerere(&merge_rr, fd);
|
||||||
|
10
rerere.h
10
rerere.h
@ -3,9 +3,15 @@
|
|||||||
|
|
||||||
#include "string-list.h"
|
#include "string-list.h"
|
||||||
|
|
||||||
extern int setup_rerere(struct string_list *);
|
#define RERERE_AUTOUPDATE 01
|
||||||
extern int rerere(void);
|
#define RERERE_NOAUTOUPDATE 02
|
||||||
|
|
||||||
|
extern int setup_rerere(struct string_list *, int);
|
||||||
|
extern int rerere(int);
|
||||||
extern const char *rerere_path(const char *hex, const char *file);
|
extern const char *rerere_path(const char *hex, const char *file);
|
||||||
extern int has_rerere_resolution(const char *hex);
|
extern int has_rerere_resolution(const char *hex);
|
||||||
|
|
||||||
|
#define OPT_RERERE_AUTOUPDATE(v) OPT_UYN(0, "rerere-autoupdate", (v), \
|
||||||
|
"update the index with reused conflict resolution if possible")
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -217,7 +217,22 @@ test_expect_success 'rerere.autoupdate' '
|
|||||||
git checkout version2 &&
|
git checkout version2 &&
|
||||||
test_must_fail git merge fifth &&
|
test_must_fail git merge fifth &&
|
||||||
test 0 = $(git ls-files -u | wc -l)
|
test 0 = $(git ls-files -u | wc -l)
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'merge --rerere-autoupdate' '
|
||||||
|
git config --unset rerere.autoupdate
|
||||||
|
git reset --hard &&
|
||||||
|
git checkout version2 &&
|
||||||
|
test_must_fail git merge --rerere-autoupdate fifth &&
|
||||||
|
test 0 = $(git ls-files -u | wc -l)
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'merge --no-rerere-autoupdate' '
|
||||||
|
git config rerere.autoupdate true
|
||||||
|
git reset --hard &&
|
||||||
|
git checkout version2 &&
|
||||||
|
test_must_fail git merge --no-rerere-autoupdate fifth &&
|
||||||
|
test 2 = $(git ls-files -u | wc -l)
|
||||||
'
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
Loading…
Reference in New Issue
Block a user