Despite what is written in git log documentation, the command invoked with -m option does not always output one record for each merge parent. If contents of a merge commit is the same as one of its parents, it does not output anything for said parent. Identifying this parent just from git log output is impossible with custom pretty formatting. So the ugly solution of this problem goes like this: when number of collected records for a commit is inconsistent with the number of parents, execute another git log command to find tree hashes of this commit and its parents, and identify, which of them are the same.
Since sometimes git log provider returns commits with reversed parents due to GitBekParentFixer existence, saving just a list of changes into index was insufficient.
Persistent map containing parents list for every commit was added.
GitBekParentFixer is required for the following situation: a user pulls commits from the remote with merge, and then pushes merged branch back. This creates incorrect order of parents for automatic merge commits (changes that were in the remote branch should go first and be displayed on the left). GitBekParentFixer finds such commits, filtering log by message, and reverses parent back for them. This is obviously a hack, but simpler and straighter solution is not yet developed.
Since now indexes know changed files from all of the parents in merge commits, this information could be utilized to correctly build file history and thus fix some of the issues with it.
Essentially dfs is employed, same as before. But now algorithm works in two passes.
In the first pass, file name in each commit is calculated while doing a dfs on the visible graph.
The trick here is that now for getting changes a commit and a parent index is required (and not just a commit, as before). But in the visible graph, a commit parent is not its real parent in git.
To get a real parent, path between two commits is obtained with bfs.
In the second pass, some commits that have unrelated changes or are trivial merges are thrown out. During this stage some related trivial merges can be thrown out. This is going to be fixed later.
IDEA-170468
Data for all of the parents is required for correct file history in case of file renamed in one of the branch. Also, since we are changing index format anyway, keep information which name was before and which was after for renames. This will help to simplify file history.
Move getModifiedPaths and getRenamedPaths from VcsChangesLazilyParsedDetails to the new interface and add parent parameter. Add getChanges(parent) method. This require to keep changes with parents as well as merged changes for merge commits, since a lot of clients currently need merged changes.
Index temporary indexes changes with the first parent (that are incoming changes for merge commits).