static git_commit* FindFileRecentCommit(git_repository* repository, const CString& path) { CAutoRevwalk walk; if (git_revwalk_new(walk.GetPointer(), repository)) return nullptr; CStringA pathA = CUnicodeUtils::GetUTF8(path); if (pathA.GetLength() >= MAX_PATH) return nullptr; const char *pathC = pathA; char folder[MAX_PATH] = {0}, file[MAX_PATH] = {0}; const char *slash = strrchr(pathC, '/'); if (slash) { strncpy(folder, pathC, slash - pathC + 1); folder[slash - pathC + 1] = '\0'; strcpy(file, slash + 1); } else { folder[0] = '\0'; strcpy(file, pathC); } TreewalkStruct treewalkstruct = { folder, file }; if (git_revwalk_push_head(walk)) return nullptr; git_oid oid; CAutoCommit commit; while (!git_revwalk_next(&oid, walk)) { if (git_commit_lookup(commit.GetPointer(), repository, &oid)) return nullptr; CAutoTree tree; if (git_commit_tree(tree.GetPointer(), commit)) return nullptr; memset(&treewalkstruct.oid.id, 0, sizeof(treewalkstruct.oid.id)); int ret = git_tree_walk(tree, GIT_TREEWALK_PRE, TreewalkCB_FindFileRecentCommit, &treewalkstruct); if (ret < 0 && ret != GIT_EUSER) return nullptr; // check if file not found if (git_oid_iszero(&treewalkstruct.oid)) return nullptr; bool diff = true; // for merge point, check if it is different to all parents, if yes then there are real change in the merge point. // if no parent then of course it is different for (unsigned int i = 0; i < git_commit_parentcount(commit); ++i) { CAutoCommit commit2; if (git_commit_parent(commit2.GetPointer(), commit, i)) return nullptr; CAutoTree tree2; if (git_commit_tree(tree2.GetPointer(), commit2)) return nullptr; TreewalkStruct treewalkstruct2 = { folder, file }; memset(&treewalkstruct2.oid.id, 0, sizeof(treewalkstruct2.oid.id)); int ret = git_tree_walk(tree2, GIT_TREEWALK_PRE, TreewalkCB_FindFileRecentCommit, &treewalkstruct2); if (ret < 0 && ret != GIT_EUSER) return nullptr; if (!git_oid_cmp(&treewalkstruct.oid, &treewalkstruct2.oid)) diff = false; else if (git_revwalk_hide(walk, git_commit_parent_id(commit, i))) return nullptr; } if (diff) break; } return commit.Detach(); }