@@ -461,23 +461,51 @@ pub fn unapply_filter(
461
461
462
462
if tid == git2:: Oid :: zero ( ) && parent_count == 2 {
463
463
// 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 (
466
494
original_parents_refs[ 0 ] ,
467
495
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 ;
481
509
}
482
510
}
483
511
@@ -486,11 +514,14 @@ pub fn unapply_filter(
486
514
// more and maybe consider allowing a manual override as last resort.
487
515
tracing:: warn!( "rejecting merge" ) ;
488
516
let msg = format ! (
489
- "rejecting merge with {} parents:\n {:?}\n 1) {:?}\n 2) {:?}" ,
517
+ "rejecting merge with {} parents:\n {:?} ({:?}) \n 1) {:?} ({:?}) \n 2) {:?} ({:?}) " ,
490
518
parent_count,
491
519
module_commit. summary( ) . unwrap_or_default( ) ,
520
+ module_commit. id( ) ,
492
521
original_parents_refs[ 0 ] . summary( ) . unwrap_or_default( ) ,
522
+ original_parents_refs[ 0 ] . id( ) ,
493
523
original_parents_refs[ 1 ] . summary( ) . unwrap_or_default( ) ,
524
+ original_parents_refs[ 1 ] . id( ) ,
494
525
) ;
495
526
return Err ( josh_error ( & msg) ) ;
496
527
}
0 commit comments