in src/commit_interleaver.h [801:869]
int commit_interleaver::mark_independent_targets(MergeRequest &merge) {
if (!merge.is_octopus) {
assert(merge.targets.size() == 1);
if (!head) {
merge.targets.front().is_independent = true;
return 0;
}
if (head == merge.targets.front().mono) {
merge.head_is_independent = true;
return 0;
}
// Just assume they're independent. There's work done already when
// preparing sources to ensure that generated merges will not be redundant,
// only including them if they're newer than some mandatory commit to
// merge. It's too expensive to call git-merge-base on every repeat merge.
merge.head_is_independent = merge.targets.front().is_independent = true;
return 0;
}
// fprintf(stderr, "mark independent targets\n");
assert(!merge.targets.empty());
// Figure out which ones are independent.
merge.head_is_independent = false;
std::vector<sha1_ref> commits;
if (head)
commits.push_back(head);
for (const MergeTarget &target : merge.targets)
if (target.mono != head)
commits.push_back(target.mono);
if (commits.size() > 1)
if (cache.merge_base_independent(commits))
return error("failed to find independent target commits");
// There should be at least one, or we have a logic bug.
assert(!commits.empty());
// Update the flags.
std::sort(commits.begin(), commits.end());
if (head)
if (std::binary_search(commits.begin(), commits.end(), head))
merge.head_is_independent = true;
for (MergeTarget &target : merge.targets)
if (target.mono != head)
if (std::binary_search(commits.begin(), commits.end(), target.mono))
target.is_independent = true;
// Put the independent targets first.
std::stable_sort(merge.targets.begin(), merge.targets.end(),
[](const MergeTarget &lhs, const MergeTarget &rhs) {
if (lhs.is_independent > rhs.is_independent)
return true;
if (lhs.is_independent < rhs.is_independent)
return false;
// Prefer putting a repeat commit first, since it makes
// the first commit from a new branch land better.
return lhs.source->is_repeat > rhs.source->is_repeat;
});
// There should be at least one, or we have a logic bug.
assert(merge.head_is_independent || merge.targets.front().is_independent);
// fprintf(stderr, "sorted targets\n");
// for (auto &target : merge.targets)
// fprintf(stderr, " - %s (independent = %d)\n",
// target.commit->to_string().c_str(), target.is_independent);
return 0;
}