@@ -461,23 +461,51 @@ pub fn unapply_filter(
461461
462462 if tid == git2:: Oid :: zero ( ) && parent_count == 2 {
463463 // If we could not select one of the parents, try to merge them.
464-
465- if let Ok ( mut merged_index) = transaction. repo ( ) . merge_commits (
464+ // We expect conflicts to occur only in the paths that are present in
465+ // the filtered commit.
466+ // As we are going to replace the contents of these files with commit being
467+ // pushed, we can ignore those conflicts. To do that we perform the merge
468+ // twice: Once with the "ours" and once with the "theirs" merge file favor.
469+ // After that we do "unapply()" on both resulting trees, which will replace
470+ // the files selected by the filter with the content being pushed.
471+ // If our assumption was correct and all conflicts were in filtered files,
472+ // both resulting trees will be the same and we can pick the result to proceed.
473+
474+ let mut mergeopts = git2:: MergeOptions :: new ( ) ;
475+ mergeopts. file_favor ( git2:: FileFavor :: Ours ) ;
476+
477+ let mut merged_index = transaction. repo ( ) . merge_commits (
478+ original_parents_refs[ 0 ] ,
479+ original_parents_refs[ 1 ] ,
480+ Some ( & mergeopts) ,
481+ ) ?;
482+ let base_tree = merged_index. write_tree_to ( transaction. repo ( ) ) ?;
483+ let tid_ours = filter:: unapply (
484+ transaction,
485+ filterobj,
486+ tree. clone ( ) ,
487+ transaction. repo ( ) . find_tree ( base_tree) ?,
488+ ) ?
489+ . id ( ) ;
490+
491+ mergeopts. file_favor ( git2:: FileFavor :: Theirs ) ;
492+
493+ let mut merged_index = transaction. repo ( ) . merge_commits (
466494 original_parents_refs[ 0 ] ,
467495 original_parents_refs[ 1 ] ,
468- None ,
469- ) {
470- // If we can auto merge without conflicts, take the result.
471- if !merged_index . has_conflicts ( ) {
472- let base_tree = merged_index . write_tree_to ( transaction. repo ( ) ) ? ;
473- tid = filter :: unapply (
474- transaction ,
475- filterobj ,
476- tree ,
477- transaction . repo ( ) . find_tree ( base_tree ) ? ,
478- ) ?
479- . id ( ) ;
480- }
496+ Some ( & mergeopts ) ,
497+ ) ? ;
498+ let base_tree = merged_index . write_tree_to ( transaction . repo ( ) ) ? ;
499+ let tid_theirs = filter :: unapply (
500+ transaction,
501+ filterobj ,
502+ tree . clone ( ) ,
503+ transaction . repo ( ) . find_tree ( base_tree ) ? ,
504+ ) ?
505+ . id ( ) ;
506+
507+ if tid_ours == tid_theirs {
508+ tid = tid_ours ;
481509 }
482510 }
483511
@@ -486,11 +514,14 @@ pub fn unapply_filter(
486514 // more and maybe consider allowing a manual override as last resort.
487515 tracing:: warn!( "rejecting merge" ) ;
488516 let msg = format ! (
489- "rejecting merge with {} parents:\n {:?}\n 1) {:?}\n 2) {:?}" ,
517+ "rejecting merge with {} parents:\n {:?} ({:?}) \n 1) {:?} ({:?}) \n 2) {:?} ({:?}) " ,
490518 parent_count,
491519 module_commit. summary( ) . unwrap_or_default( ) ,
520+ module_commit. id( ) ,
492521 original_parents_refs[ 0 ] . summary( ) . unwrap_or_default( ) ,
522+ original_parents_refs[ 0 ] . id( ) ,
493523 original_parents_refs[ 1 ] . summary( ) . unwrap_or_default( ) ,
524+ original_parents_refs[ 1 ] . id( ) ,
494525 ) ;
495526 return Err ( josh_error ( & msg) ) ;
496527 }
0 commit comments