Changes in v5: - Marked error messages for translation and tweaked them as suggested by Phillip - Reworded the message of 2/2 as suggested by Phillip - Removed the change to gitk's doc in 2/2 as pointed out by Johannes - Fixed the trailers in 2/2 - Improved the doc in 2/2 as suggested by Phillip and Jean-Noël Changes in v4: - Added a commit message for 2/2 detailing the use case and summarizing the discussion in the thread - Adjusted the documentation of the option --- Michael Lohmann (2): revision: ensure MERGE_HEAD is a ref in prepare_show_merge revision: implement `git log --merge` also for rebase/cherry-pick/revert Documentation/rev-list-options.txt | 7 +++++-- revision.c | 27 +++++++++++++++++++++++---- 2 files changed, 28 insertions(+), 6 deletions(-) --- base-commit: 186b115d3062e6230ee296d1ddaa0c4b72a464b5 change-id: 20240210-ml-log-merge-with-cherry-pick-and-other-pseudo-heads-05bd8e8797db Range-diff versus v4: 1: 37405be1a3 ! 1: c9536431d1 revision: ensure MERGE_HEAD is a ref in prepare_show_merge @@ Commit message Helped-by: Junio C Hamano <gitster@xxxxxxxxx> Signed-off-by: Michael Lohmann <mi.al.lohmann@xxxxxxxxx> Signed-off-by: Junio C Hamano <gitster@xxxxxxxxx> + Signed-off-by: Philippe Blain <levraiphilippeblain@xxxxxxxxx> ## revision.c ## @@ revision.c: static void prepare_show_merge(struct rev_info *revs) @@ revision.c: static void prepare_show_merge(struct rev_info *revs) + &oid, NULL)) die("--merge without MERGE_HEAD?"); + if (is_null_oid(&oid)) -+ die("MERGE_HEAD is a symbolic ref???"); ++ die(_("MERGE_HEAD is a symbolic ref?")); other = lookup_commit_or_die(&oid, "MERGE_HEAD"); add_pending_object(revs, &head->object, "HEAD"); add_pending_object(revs, &other->object, "MERGE_HEAD"); 2: 6ac1608809 ! 2: 1641c4be81 revision: implement `git log --merge` also for rebase/cherry-pick/revert @@ Commit message to merge conflicts also for other mergy operations besides merges, like cherry-pick, revert and rebase. - For rebases, an interesting range to look at is HEAD...REBASE_HEAD, - since the conflicts are usually caused by how the code changed - differently on HEAD since REBASE_HEAD forked from it. + For rebases and cherry-picks, an interesting range to look at is + HEAD...{REBASE_HEAD,CHERRY_PICK_HEAD}, since even if all the commits + included in that range are not directly part of the 3-way merge, + conflicts encountered during these operations can indeed be caused by + changes introduced in preceding commits on both sides of the history. - For cherry-picks and revert, it is less clear that - HEAD...CHERRY_PICK_HEAD and HEAD...REVERT_HEAD are indeed interesting - ranges, since these commands are about applying or unapplying a single - (or a few, for cherry-pick) commit(s) on top of HEAD. However, conflicts - encountered during these operations can indeed be caused by changes - introduced in preceding commits on both sides of the history. + For revert, as we are (most likely) reversing changes from a previous + commit, an appropriate range is REVERT_HEAD..HEAD, which is equivalent + to REVERT_HEAD...HEAD and to HEAD...REVERT_HEAD, if we keep HEAD and its + parents on the left side of the range. - Adjust the code in prepare_show_merge so it constructs the range - HEAD...$OTHER for each of OTHER={MERGE_HEAD, CHERRY_PICK_HEAD, - REVERT_HEAD or REBASE_HEAD}. Note that we try these pseudorefs in order, - so keep REBASE_HEAD last since the three other operations can be - performed during a rebase. Note also that in the uncommon case where - $OTHER and HEAD do not share a common ancestor, this will show the - complete histories of both sides since their root commits, which is the - same behaviour as currently happens in that case for HEAD and - MERGE_HEAD. + As such, adjust the code in prepare_show_merge so it constructs the + range HEAD...$OTHER for OTHER={MERGE_HEAD, CHERRY_PICK_HEAD, REVERT_HEAD + or REBASE_HEAD}. Note that we try these pseudorefs in order, so keep + REBASE_HEAD last since the three other operations can be performed + during a rebase. Note also that in the uncommon case where $OTHER and + HEAD do not share a common ancestor, this will show the complete + histories of both sides since their root commits, which is the same + behaviour as currently happens in that case for HEAD and MERGE_HEAD. Adjust the documentation of this option accordingly. - Co-authored-by: Philippe Blain <levraiphilippeblain@xxxxxxxxx> Co-authored-by: Johannes Sixt <j6t@xxxxxxxx> - Signed-off-by: Philippe Blain <levraiphilippeblain@xxxxxxxxx> + Co-authored-by: Philippe Blain <levraiphilippeblain@xxxxxxxxx> Signed-off-by: Michael Lohmann <mi.al.lohmann@xxxxxxxxx> [jc: tweaked in j6t's precedence fix that tries REBASE_HEAD last] Signed-off-by: Junio C Hamano <gitster@xxxxxxxxx> - - ## Documentation/gitk.txt ## -@@ Documentation/gitk.txt: linkgit:git-rev-list[1] for a complete list. - - --merge:: - -- After an attempt to merge stops with conflicts, show the commits on -- the history between two branches (i.e. the HEAD and the MERGE_HEAD) -- that modify the conflicted files and do not exist on all the heads -- being merged. -+ Show commits touching conflicted paths in the range `HEAD...$OTHER`, -+ where `$OTHER` is the first existing pseudoref in `MERGE_HEAD`, -+ `CHERRY_PICK_HEAD`, `REVERT_HEAD` or `REBASE_HEAD`. Only works -+ when the index has unmerged entries. - - --left-right:: - + Signed-off-by: Philippe Blain <levraiphilippeblain@xxxxxxxxx> ## Documentation/rev-list-options.txt ## @@ Documentation/rev-list-options.txt: See also linkgit:git-reflog[1]. @@ Documentation/rev-list-options.txt: See also linkgit:git-reflog[1]. --merge:: - After a failed merge, show refs that touch files having a - conflict and don't exist on all heads to merge. -+ Show commits touching conflicted paths in the range `HEAD...$OTHER`, -+ where `$OTHER` is the first existing pseudoref in `MERGE_HEAD`, ++ Show commits touching conflicted paths in the range `HEAD...<other>`, ++ where `<other>` is the first existing pseudoref in `MERGE_HEAD`, + `CHERRY_PICK_HEAD`, `REVERT_HEAD` or `REBASE_HEAD`. Only works -+ when the index has unmerged entries. ++ when the index has unmerged entries. This option can be used to show ++ relevant commits when resolving conflicts from a 3-way merge. --boundary:: Output excluded boundary commits. Boundary commits are @@ revision.c: static void add_pending_commit_list(struct rev_info *revs, + RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE, + oid, NULL)) { + if (is_null_oid(oid)) -+ die("%s is a symbolic ref???", other_head[i]); ++ die(_("%s is a symbolic ref?"), other_head[i]); + return other_head[i]; + } + -+ die("--merge without MERGE_HEAD, CHERRY_PICK_HEAD, REVERT_HEAD or REBASE_HEAD?"); ++ die(_("--merge requires one of the pseudorefs MERGE_HEAD, CHERRY_PICK_HEAD, REVERT_HEAD or REBASE_HEAD")); +} + static void prepare_show_merge(struct rev_info *revs) @@ revision.c: static void prepare_show_merge(struct rev_info *revs) - &oid, NULL)) - die("--merge without MERGE_HEAD?"); - if (is_null_oid(&oid)) -- die("MERGE_HEAD is a symbolic ref???"); +- die(_("MERGE_HEAD is a symbolic ref?")); - other = lookup_commit_or_die(&oid, "MERGE_HEAD"); + other_name = lookup_other_head(&oid); + other = lookup_commit_or_die(&oid, other_name);