diff --git a/doc/workingcopy.md b/doc/workingcopy.md index 4ecea6c..375694a 100644 --- a/doc/workingcopy.md +++ b/doc/workingcopy.md @@ -26,6 +26,24 @@ $wc->checkout('origin/master', 'master'); You can also pass a *Reference* or a *Commit*. +Merge a revision +---------------- + +You can merge any revision into the current branch using the *merge* method. +A second argument can be used to pass extra options to the underlying +`git merge` command: + +```php +// git merge origin/develop +$wc->merge('origin/develop'); + +// git merge --no-ff origin/develop +$wc->merge('origin/develop', ['--no-ff']); +``` + +You can also pass a *Reference* or a *Commit*. A `RuntimeException` is thrown +if the merge fails (for instance because of a conflict). + Staged modifications -------------------- diff --git a/src/Gitonomy/Git/WorkingCopy.php b/src/Gitonomy/Git/WorkingCopy.php index aa96d52..3d3612d 100644 --- a/src/Gitonomy/Git/WorkingCopy.php +++ b/src/Gitonomy/Git/WorkingCopy.php @@ -101,6 +101,29 @@ public function checkout($revision, ?string $branch = null): static return $this; } + /** + * Merges a revision into the current branch. + * + * @param Commit|Reference|string $revision + * @param string[] $args extra arguments for the merge command (e.g. ``['--no-ff']``) + */ + public function merge($revision, array $args = []): static + { + if ($revision instanceof Commit) { + $args[] = $revision->getHash(); + } elseif ($revision instanceof Reference) { + $args[] = $revision->getFullname(); + } elseif (\is_string($revision)) { + $args[] = $revision; + } else { + throw new InvalidArgumentException(\sprintf('Unknown type "%s"', \gettype($revision))); + } + + $this->run('merge', $args); + + return $this; + } + private function run(string $command, array $args = []): ?string { return $this->repository->run($command, $args); diff --git a/tests/Gitonomy/Git/Tests/WorkingCopyTest.php b/tests/Gitonomy/Git/Tests/WorkingCopyTest.php index 3e88ebc..1e532e7 100644 --- a/tests/Gitonomy/Git/Tests/WorkingCopyTest.php +++ b/tests/Gitonomy/Git/Tests/WorkingCopyTest.php @@ -110,4 +110,30 @@ public function testGetUntracked(): void $this->assertContains('untracked.txt', $wc->getUntrackedFiles()); } + + public function testMerge(): void + { + $repository = self::createFoobarRepository(false); + $repository->run('config', ['--local', 'user.name', '"Unit Test"']); + $repository->run('config', ['--local', 'user.email', '"unit_test@unit-test.com"']); + $wc = $repository->getWorkingCopy(); + $wc->checkout('master'); + + $wc->merge('origin/diff-features'); + + $head = $repository->getHeadCommit(); + $this->assertCount(2, $head->getParents(), 'Merge produced a merge commit'); + $this->assertFileExists($repository->getWorkingDir().'/script_A.php'); + } + + public function testMergeConflict(): void + { + $this->expectException(RuntimeException::class); + + $repository = self::createFoobarRepository(false); + $wc = $repository->getWorkingCopy(); + $wc->checkout('master'); + + $wc->merge('origin/new-feature'); + } }