Unexpected file changes and git access #37
Labels
No labels
Compat/Breaking
Kind
Bad merge
Kind
Bug
Kind
Documentation
Kind
Enhancement
Kind
Feature
Kind
New language
Kind
Security
Kind
Testing
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Reviewed
Confirmed
Reviewed
Duplicate
Reviewed
Invalid
Reviewed
Won't Fix
Status
Abandoned
Status
Blocked
Status
Need More Info
No milestone
No project
No assignees
4 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: mergiraf/mergiraf#37
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Given the file:
I get the following output from mergiraf:
I don't understand why mergiraf is trying to access my current git repository? All the information it needs should be in the current file.
It also looks like it modifies the file, removing the helpful commit information from the conflict markers:
The output isn't great indeed. The tool first tries to solve the conflicts just looking at the file you provided, fails, and then tries to solve it again with the original revisions retrieved from Git. That's because in general, some conflicts can only be solved from the original revisions and not the merged file with conflicts.
In this case, since there are no merged sections in your file, the file is indeed equivalent to the three revisions, so it's indeed pointless to try fetching the revisions from Git. One could potentially add logic to detect such cases, but I think it wouldn't be used so often (your example strikes me as a rather unusual one in real use cases).
The removal of the commit ids is indeed concerning, and definitely something that I'd like to fix. There are two problems:
How so? When you have the base, left and right (diff3 format like this), you can construct the file state exclusively from the file with conflicts.
I guess if you have a diff2 conflict style you need to consult git?
Not if some parts of the file with conflicts were successfully merged. In some cases, it's important to have the original revisions, for instance for move/edit conflicts.
So I researched this a little, and I think I know the answer to
The method where all of this takes is
resolve_merge_cascading
. It cascades as follows:structured_resolution
1 -- succeedsstructured_merge
2 -- fails because of the lack of Git revisionsparsed_merge
), and the one fromstructured_resolution
. To find out which one's best, it callsselect_best_merge
select_best_merge
finds the merge with the smallestconflict_mass
which doesn't have additional conflict. Neither of the 2 merges has additional conflicts, so it all comes toconflict_mass
structured_resolution
reports having aconflict_mass
of 61, which is smaller thanparsed_merge
's 79. Therefore, the former gets written into the file.Possible solutions
1
structured_resolution
'sconflict_mass
reporting so that it's equal to that of an identicalparsed_merge
select_best_merge
to preferparsed_merge
in case of a tieThen, the following would happen in cases like in this issue:
structured_resolution
doesn't win overparsed_merge
select_best_merge
returnsparsed_merge
mergiraf solve
recognizesparsed_merge
by its `method="original", and throws it away without writing/outputting anything:Ok(merged) if merged.method == "original" => 1,
2
select_best_merge
return anOption
, so that ifparsed_merge
seems to be the (equally) best, it returnsNone
Then:
parsed_merge
ties withstructured_resolution
select_best_merge
returnsNone
resolve_merge_cascading
catches that and returns a correspondingErr
mergiraf solve
handles that reasonably:Err(e) => {
warn!("Mergiraf: {e}");
1
}
structured_merge(..., parsed_merge=Some(parsed_merge))
↩︎structured_merge(..., parsed_merge=None)
↩︎Ok, so the answer is much dumber than I thought -- but it has to do with the reason why
structured_resolution
fails in the first place.The thing is that
structured_resolution
(just likestructured_merge
) uses treesitter to parse all three sides of the conflicts and then merges by matching the parts of three trees. The image below shows the matching between the base revision (here,use email::send;
) and the left one (use email::{send, validate};
).For one, it shows why the conflict couldn't be resolved completely -- the lone
email::send
in base is represented asscoped_identifier
, whereas a very similaremail::{send,...}
in left becomes ascoped_use_list
, which prevents their child nodes (email
,::
, andsend
) from being matched. I'm actually not sure whether this is an error on treesitter side (someone more familiar with it might give some context), or maybe this is the correct representation and it's us who'd need to teach Mergiraf to handle such cases (which would be a nice enhancement IMO).At the same time, it shows why the conflict from
resolved_merge
is nevertheless smaller than the one inparsed_merge
-- the former at least manages to match the common tokensuse
and;
, and as such, reducesconflict_mass
, whileparsed_merge
reduces nothing (by definition, since it just parses the input file). To prove this, here is some debugprint fromMergedTree::conflict_mass
andParsedMerge::conflict_mass
, respectively:All in all, since #74 has solved the stripped revision names problem, the outputs from both merge methods should be identical, so this is pretty much solved I'd say? Maybe, it's just the worrying output that needs to be silenced.
Yes, this is a known limitation of the current algorithm. I agree would be worth solving, but I am not sure how.
Yes. I guess one could still consider changing how the conflict mass is computed, to measure the size of conflicts when fully rendered (expanded to match line boundaries) instead of their more compact version. But I am not sure it's worth it, because arguably, merge tools should be able to highlight the differences between the lines to make the conflict resolution simpler (meaning that the user's effort corresponds more or less to the compact conflict mass).
I think the leftover issue should be pretty much solved by #423 in the sense that it changes the message to be clearer?
The message should now be along the lines of
Agreed, let's close this.