/** * Merges the two branches * @param bool $ff Fast-forward the base branch if possible * @param int $mode Merge method to use * ({@link self::THEIRS} to solve conflicts by picking from the base branch, * {@link self::OURS} to solve conflicts by picking from the head branch, * {@link self::MANUAL} to write a conflicted file to the tree) * @return boolean|\gihp\Tree true when fast-forwarded, false when the base branch is up-to-date, * {@link \gihp\Tree} The merged tree in all other cases * @throws \RuntimeException When there is no common ancestor */ public function merge($ff = true, $mode = self::MANUAL) { $base_history = $this->base->getHistory(); $head_history = $this->head->getHistory(); $base_history_sha = array(); foreach ($base_history as $commit) { $base_history_sha[] = $commit->getSHA1(); } $head_history_sha = array(); foreach ($head_history as $commit) { $head_history_sha[] = $commit->getSHA1(); } $head_diff = array_diff($head_history_sha, $base_history_sha); $base_diff = array_diff($base_history_sha, $head_history_sha); if (count($base_diff) == 0 && count($head_diff) > 0) { // Base has no modifications since head branched off if ($ff) { // Fast-forward the base branch $this->base->advanceHead($this->head->getHeadCommit()); return true; } else { return $this->head->getTree(); } } if (count($head_diff) == 0) { // Base is up-to-date, do nothing return false; } // Find last common commit $last_common_idx_head = array_search($head_diff[0], $head_history_sha) + 1; $last_common_idx_base = array_search($base_diff[0], $base_history_sha) + 1; $last_common_commit_head_sha = $head_history_sha[$last_common_idx_head]; $last_common_commit_base_sha = $base_history_sha[$last_common_idx_base]; if ($last_common_commit_base_sha != $last_common_commit_head_sha) { throw new \RuntimeException('Cannot find the last common commit.'); } $last_common_commit = $base_history[$last_common_idx_base]; $last_common_tree = $last_common_commit->getTree(); // Load latest trees $base_latest_tree = $this->base->getTree(); $head_latest_tree = $this->head->getTree(); $final_tree = self::treeMerge($last_common_tree, $base_latest_tree, $head_latest_tree, $mode); return new Tree($final_tree); }
/** * Removes a branch * @param Branch $branch The branch to remove */ public function removeBranch(Branch $branch) { $this->io->removeRef($branch->getHead()); }