commit fdf3c2d3876d076bf098461a4d147227126588b4 from: Stefan Sperling date: Thu Jun 17 09:01:05 2021 UTC 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. commit - 1d0f405485b02cc4480ea188879e4122e0ea32bd commit + fdf3c2d3876d076bf098461a4d147227126588b4 blob - b8c328a2f9b853caabcc322afe5c68eefd3b4ccb blob + fa402b0446d11c215371183b598bd9573467a1d0 --- lib/diff3.c +++ 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, 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; blob - c056426dd1569f33cd5459cba2caaa263be5224d blob + 6262295fc0820142511469142f7dfe853a485953 --- lib/got_lib_diff.h +++ lib/got_lib_diff.h @@ -63,7 +63,7 @@ const struct got_error *got_diffreg_close(FILE *, char 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 *); blob - 522c2fe12ca9c96345952c0586dcca8194d69202 blob + 77e9ecb628d437b68e991e2de6d272b5053ad9e0 --- lib/worktree.c +++ lib/worktree.c @@ -771,7 +771,7 @@ merge_file(int *local_changes_subsumed, struct got_wor 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_wor 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_wor 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)