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>
Junio C Hamano committed
Dec 4, 2009 at 00:20 UTC
cb6020bb017405cc3e7f1faea6f30d4fd1b62e70
12 files changed
+77
-18
Documentation/git-merge.txt
+6
-1
@@ -10,7 +10,7 @@ SYNOPSIS
10
--------
11
[verse]
12
'git merge' [-n] [--stat] [--no-commit] [--squash] [-s <strategy>]...
13
- [-m <msg>] <remote>...
13
+ [--[no-]rerere-autoupdate] [-m <msg>] <remote>...
14
'git merge' <msg> HEAD <remote>...
15
16
DESCRIPTION
@@ -33,6 +33,11 @@ include::merge-options.txt[]
33
used to give a good default for automated 'git merge'
34
invocations.
35
36
+--rerere-autoupdate::
37
+--no-rerere-autoupdate::
38
+ Allow the rerere mechanism to update the index with the
39
+ result of auto-conflict resolution if possible.
40
+
41
<remote>...::
42
Other branch heads to merge into our branch. You need at
43
least one <remote>. Specifying more than one <remote>
builtin-commit.c
+1
-1
@@ -1150,7 +1150,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
1150
"new_index file. Check that disk is not full or quota is\n"
1151
"not exceeded, and then \"git reset HEAD\" to recover.");
1152
1153
- rerere();
1153
+ rerere(0);
1154
run_hook(get_index_file(), "post-commit", NULL);
1155
if (!quiet)
1156
print_summary(prefix, commit_sha1);
builtin-merge.c
+3
-1
@@ -52,6 +52,7 @@ static struct strategy **use_strategies;
52
static size_t use_strategies_nr, use_strategies_alloc;
53
static const char *branch;
54
static int verbosity;
55
+static int allow_rerere_auto;
56
57
static struct strategy all_strategy[] = {
58
{ "recursive", DEFAULT_TWOHEAD | NO_TRIVIAL },
@@ -170,6 +171,7 @@ static struct option builtin_merge_options[] = {
171
"allow fast-forward (default)"),
172
OPT_BOOLEAN(0, "ff-only", &fast_forward_only,
173
"abort if fast-forward is not possible"),
174
+ OPT_RERERE_AUTOUPDATE(&allow_rerere_auto),
175
OPT_CALLBACK('s', "strategy", &use_strategies, "strategy",
176
"merge strategy to use", option_parse_strategy),
177
OPT_CALLBACK('m', "message", &merge_msg, "message",
@@ -790,7 +792,7 @@ static int suggest_conflicts(void)
792
}
793
}
794
fclose(fp);
793
- rerere();
795
+ rerere(allow_rerere_auto);
796
printf("Automatic merge failed; "
797
"fix conflicts and then commit the result.\n");
798
return 1;
builtin-rerere.c
+16
-7
@@ -101,15 +101,24 @@ static int diff_two(const char *file1, const char *label1,
101
int cmd_rerere(int argc, const char **argv, const char *prefix)
102
{
103
struct string_list merge_rr = { NULL, 0, 0, 1 };
104
- int i, fd;
105
-
104
+ int i, fd, flags = 0;
105
+
106
+ if (2 < argc) {
107
+ if (!strcmp(argv[1], "-h"))
108
+ usage(git_rerere_usage);
109
+ if (!strcmp(argv[1], "--rerere-autoupdate"))
110
+ flags = RERERE_AUTOUPDATE;
111
+ else if (!strcmp(argv[1], "--no-rerere-autoupdate"))
112
+ flags = RERERE_NOAUTOUPDATE;
113
+ if (flags) {
114
+ argc--;
115
+ argv++;
116
+ }
117
+ }
118
if (argc < 2)
107
- return rerere();
108
-
109
- if (!strcmp(argv[1], "-h"))
110
- usage(git_rerere_usage);
119
+ return rerere(flags);
120
112
- fd = setup_rerere(&merge_rr);
121
+ fd = setup_rerere(&merge_rr, flags);
122
if (fd < 0)
123
return 0;
124
builtin-revert.c
+3
-1
@@ -38,6 +38,7 @@ static const char * const cherry_pick_usage[] = {
38
static int edit, no_replay, no_commit, mainline, signoff;
39
static enum { REVERT, CHERRY_PICK } action;
40
static struct commit *commit;
41
+static int allow_rerere_auto;
42
43
static const char *me;
44
@@ -57,6 +58,7 @@ static void parse_args(int argc, const char **argv)
58
OPT_BOOLEAN('r', NULL, &noop, "no-op (backward compatibility)"),
59
OPT_BOOLEAN('s', "signoff", &signoff, "add Signed-off-by:"),
60
OPT_INTEGER('m', "mainline", &mainline, "parent number"),
61
+ OPT_RERERE_AUTOUPDATE(&allow_rerere_auto),
62
OPT_END(),
63
};
64
@@ -395,7 +397,7 @@ static int revert_or_cherry_pick(int argc, const char **argv)
397
die ("Error wrapping up %s", defmsg);
398
fprintf(stderr, "Automatic %s failed.%s\n",
399
me, help_msg(commit->object.sha1));
398
- rerere();
400
+ rerere(allow_rerere_auto);
401
exit(1);
402
}
403
if (commit_lock_file(&msg_file) < 0)
git-am.sh
+5
-1
@@ -30,6 +30,7 @@ skip skip the current patch
30
abort restore the original branch and abort the patching operation.
31
committer-date-is-author-date lie about committer date
32
ignore-date use current timestamp for author date
33
+rerere-autoupdate update the index with reused conflict resolution if possible
34
rebasing* (internal use for git-rebase)"
35
36
. git-sh-setup
@@ -135,7 +136,7 @@ It does not apply to blobs recorded in its index."
136
export GIT_MERGE_VERBOSITY=0
137
fi
138
git-merge-recursive $orig_tree -- HEAD $his_tree || {
138
- git rerere
139
+ git rerere $allow_rerere_autoupdate
140
echo Failed to merge in the changes.
141
exit 1
142
}
@@ -293,6 +294,7 @@ resolvemsg= resume= scissors= no_inbody_headers=
294
git_apply_opt=
295
committer_date_is_author_date=
296
ignore_date=
297
+allow_rerere_autoupdate=
298
299
while test $# != 0
300
do
@@ -340,6 +342,8 @@ do
342
committer_date_is_author_date=t ;;
343
--ignore-date)
344
ignore_date=t ;;
345
+ --rerere-autoupdate|--no-rerere-autoupdate)
346
+ allow_rerere_autoupdate="$1" ;;
347
-q|--quiet)
348
GIT_QUIET=t ;;
349
--)
git-rebase.sh
+5
-1
@@ -50,6 +50,7 @@ diffstat=$(git config --bool rebase.stat)
50
git_am_opt=
51
rebase_root=
52
force_rebase=
53
+allow_rerere_autoupdate=
54
55
continue_merge () {
56
test -n "$prev_head" || die "prev_head must be defined"
@@ -118,7 +119,7 @@ call_merge () {
119
return
120
;;
121
1)
121
- git rerere
122
+ git rerere $allow_rerere_autoupdate
123
die "$RESOLVEMSG"
124
;;
125
2)
@@ -349,6 +350,9 @@ do
350
-f|--f|--fo|--for|--forc|force|--force-r|--force-re|--force-reb|--force-reba|--force-rebas|--force-rebase)
351
force_rebase=t
352
;;
353
+ --rerere-autoupdate|--no-rerere-autoupdate)
354
+ allow_rerere_autoupdate="$1"
355
+ ;;
356
-*)
357
usage
358
;;
parse-options.c
+7
@@ -633,3 +633,10 @@ int parse_opt_with_commit(const struct option *opt, const char *arg, int unset)
633
commit_list_insert(commit, opt->value);
634
return 0;
635
}
636
+
637
+int parse_opt_tertiary(const struct option *opt, const char *arg, int unset)
638
+{
639
+ int *target = opt->value;
640
+ *target = unset ? 2 : 1;
641
+ return 0;
642
+}
parse-options.h
+3
@@ -123,6 +123,8 @@ struct option {
123
(h), PARSE_OPT_NOARG, NULL, (p) }
124
#define OPT_INTEGER(s, l, v, h) { OPTION_INTEGER, (s), (l), (v), "n", (h) }
125
#define OPT_STRING(s, l, v, a, h) { OPTION_STRING, (s), (l), (v), (a), (h) }
126
+#define OPT_UYN(s, l, v, h) { OPTION_CALLBACK, (s), (l), (v), NULL, \
127
+ (h), PARSE_OPT_NOARG, &parse_opt_tertiary }
128
#define OPT_DATE(s, l, v, h) \
129
{ OPTION_CALLBACK, (s), (l), (v), "time",(h), 0, \
130
parse_opt_approxidate_cb }
@@ -190,6 +192,7 @@ extern int parse_opt_abbrev_cb(const struct option *, const char *, int);
192
extern int parse_opt_approxidate_cb(const struct option *, const char *, int);
193
extern int parse_opt_verbosity_cb(const struct option *, const char *, int);
194
extern int parse_opt_with_commit(const struct option *, const char *, int);
195
+extern int parse_opt_tertiary(const struct option *, const char *, int);
196
197
#define OPT__VERBOSE(var) OPT_BOOLEAN('v', "verbose", (var), "be verbose")
198
#define OPT__QUIET(var) OPT_BOOLEAN('q', "quiet", (var), "be quiet")
rerere.c
+5
-3
@@ -367,7 +367,7 @@ static int is_rerere_enabled(void)
367
return 1;
368
}
369
370
-int setup_rerere(struct string_list *merge_rr)
370
+int setup_rerere(struct string_list *merge_rr, int flags)
371
{
372
int fd;
373
@@ -375,6 +375,8 @@ int setup_rerere(struct string_list *merge_rr)
375
if (!is_rerere_enabled())
376
return -1;
377
378
+ if (flags & (RERERE_AUTOUPDATE|RERERE_NOAUTOUPDATE))
379
+ rerere_autoupdate = !!(flags & RERERE_AUTOUPDATE);
380
merge_rr_path = git_pathdup("MERGE_RR");
381
fd = hold_lock_file_for_update(&write_lock, merge_rr_path,
382
LOCK_DIE_ON_ERROR);
@@ -382,12 +384,12 @@ int setup_rerere(struct string_list *merge_rr)
384
return fd;
385
}
386
385
-int rerere(void)
387
+int rerere(int flags)
388
{
389
struct string_list merge_rr = { NULL, 0, 0, 1 };
390
int fd;
391
390
- fd = setup_rerere(&merge_rr);
392
+ fd = setup_rerere(&merge_rr, flags);
393
if (fd < 0)
394
return 0;
395
return do_plain_rerere(&merge_rr, fd);
rerere.h
+8
-2
@@ -3,9 +3,15 @@
3
4
#include "string-list.h"
5
6
-extern int setup_rerere(struct string_list *);
7
-extern int rerere(void);
6
+#define RERERE_AUTOUPDATE 01
7
+#define RERERE_NOAUTOUPDATE 02
8
+
9
+extern int setup_rerere(struct string_list *, int);
10
+extern int rerere(int);
11
extern const char *rerere_path(const char *hex, const char *file);
12
extern int has_rerere_resolution(const char *hex);
13
14
+#define OPT_RERERE_AUTOUPDATE(v) OPT_UYN(0, "rerere-autoupdate", (v), \
15
+ "update the index with reused conflict resolution if possible")
16
+
17
#endif
t/t4200-rerere.sh
+15
@@ -217,7 +217,22 @@ test_expect_success 'rerere.autoupdate' '
217
git checkout version2 &&
218
test_must_fail git merge fifth &&
219
test 0 = $(git ls-files -u | wc -l)
220
+'
221
222
+test_expect_success 'merge --rerere-autoupdate' '
223
+ git config --unset rerere.autoupdate
224
+ git reset --hard &&
225
+ git checkout version2 &&
226
+ test_must_fail git merge --rerere-autoupdate fifth &&
227
+ test 0 = $(git ls-files -u | wc -l)
228
+'
229
+
230
+test_expect_success 'merge --no-rerere-autoupdate' '
231
+ git config rerere.autoupdate true
232
+ git reset --hard &&
233
+ git checkout version2 &&
234
+ test_must_fail git merge --no-rerere-autoupdate fifth &&
235
+ test 2 = $(git ls-files -u | wc -l)
236
'
237
238
test_done