use Patience diff for merging during cherrypick/backout/histedit/rebase This has been shown to prevent mis-merges in some cases. It's probably not a final solution. We should look at what Git's "recursive merge" is doing and implement something similar. Keep using Myers during update/unstage. The advantage of Myers is that it produces smaller conflict chunks, and there are no known cases of mis-merges which affect update/unstage.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
diff --git a/lib/diff3.c b/lib/diff3.c
index b8c328a..fa402b0 100644
--- a/lib/diff3.c
+++ b/lib/diff3.c
@@ -197,7 +197,8 @@ diff_output(BUF *diffbuf, const char *fmt, ...)
}
static const struct got_error*
-diffreg(BUF **d, const char *path1, const char *path2)
+diffreg(BUF **d, const char *path1, const char *path2,
+ enum got_diff_algorithm diff_algo)
{
const struct got_error *err = NULL;
FILE *f1 = NULL, *f2 = NULL, *outfile = NULL;
@@ -222,8 +223,7 @@ diffreg(BUF **d, const char *path1, const char *path2)
if (err)
goto done;
- err = got_diffreg(&diffreg_result, f1, f2,
- GOT_DIFF_ALGORITHM_MYERS, 0, 1);
+ err = got_diffreg(&diffreg_result, f1, f2, diff_algo, 0, 1);
if (err)
goto done;
@@ -262,7 +262,8 @@ done:
*/
const struct got_error *
got_merge_diff3(int *overlapcnt, int outfd, FILE *f1, FILE *f2,
- FILE *f3, const char *label1, const char *label2, const char *label3)
+ FILE *f3, const char *label1, const char *label2, const char *label3,
+ enum got_diff_algorithm diff_algo)
{
const struct got_error *err = NULL;
char *dp13, *dp23, *path1, *path2, *path3;
@@ -321,14 +322,14 @@ got_merge_diff3(int *overlapcnt, int outfd, FILE *f1, FILE *f2,
buf_free(b2);
b2 = NULL;
- err = diffreg(&d1, path1, path3);
+ err = diffreg(&d1, path1, path3, diff_algo);
if (err) {
buf_free(diffb);
diffb = NULL;
goto out;
}
- err = diffreg(&d2, path2, path3);
+ err = diffreg(&d2, path2, path3, diff_algo);
if (err) {
buf_free(diffb);
diffb = NULL;
diff --git a/lib/got_lib_diff.h b/lib/got_lib_diff.h
index c056426..6262295 100644
--- a/lib/got_lib_diff.h
+++ b/lib/got_lib_diff.h
@@ -63,7 +63,7 @@ const struct got_error *got_diffreg_close(FILE *, char *, size_t,
FILE *, char *, size_t);
const struct got_error *got_merge_diff3(int *, int, FILE *, FILE *, FILE *,
- const char *, const char *, const char *);
+ const char *, const char *, const char *, enum got_diff_algorithm);
const struct got_error *got_diff_files(struct got_diffreg_result **, FILE *,
const char *, FILE *, const char *, int, int, int, FILE *);
diff --git a/lib/worktree.c b/lib/worktree.c
index 522c2fe..77e9ecb 100644
--- a/lib/worktree.c
+++ b/lib/worktree.c
@@ -771,7 +771,7 @@ merge_file(int *local_changes_subsumed, struct got_worktree *worktree,
FILE *f_orig, FILE *f_deriv, FILE *f_deriv2, const char *ondisk_path,
const char *path, uint16_t st_mode,
const char *label_orig, const char *label_deriv, const char *label_deriv2,
- struct got_repository *repo,
+ enum got_diff_algorithm diff_algo, struct got_repository *repo,
got_worktree_checkout_cb progress_cb, void *progress_arg)
{
const struct got_error *err = NULL;
@@ -797,7 +797,7 @@ merge_file(int *local_changes_subsumed, struct got_worktree *worktree,
goto done;
err = got_merge_diff3(&overlapcnt, merged_fd, f_deriv, f_orig,
- f_deriv2, label_deriv, label_orig, label_deriv2);
+ f_deriv2, label_deriv, label_orig, label_deriv2, diff_algo);
if (err)
goto done;
@@ -1182,7 +1182,7 @@ merge_blob(int *local_changes_subsumed, struct got_worktree *worktree,
err = merge_file(local_changes_subsumed, worktree, f_orig, f_deriv,
f_deriv2, ondisk_path, path, st_mode, label_orig, label_deriv,
- NULL, repo, progress_cb, progress_arg);
+ NULL, GOT_DIFF_ALGORITHM_MYERS, repo, progress_cb, progress_arg);
done:
if (f_orig && fclose(f_orig) == EOF && err == NULL)
err = got_error_from_errno("fclose");
@@ -2922,7 +2922,8 @@ merge_file_cb(void *arg, struct got_blob_object *blob1,
err = merge_file(&local_changes_subsumed, a->worktree,
f_orig, f_deriv, f_deriv2, ondisk_path, path2,
sb.st_mode, a->label_orig, NULL, label_deriv2,
- repo, a->progress_cb, a->progress_arg);
+ GOT_DIFF_ALGORITHM_PATIENCE, repo,
+ a->progress_cb, a->progress_arg);
}
} else if (blob1) {
ie = got_fileindex_entry_get(a->fileindex, path1,
@@ -7875,7 +7876,7 @@ unstage_hunks(struct got_object_id *staged_blob_id,
err = merge_file(&local_changes_subsumed, worktree,
f_base, f, f_deriv2, ondisk_path, ie->path,
got_fileindex_perms_to_st(ie),
- label_orig, "unstaged", NULL,
+ label_orig, "unstaged", NULL, GOT_DIFF_ALGORITHM_MYERS,
repo, progress_cb, progress_arg);
}
if (err)