Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge phpunit-mock-objects into this repository #3103

Closed
sebastianbergmann opened this issue Apr 25, 2018 · 8 comments
Closed

Merge phpunit-mock-objects into this repository #3103

sebastianbergmann opened this issue Apr 25, 2018 · 8 comments
Labels
type/enhancement A new idea that should be implemented

Comments

@sebastianbergmann
Copy link
Owner

The motivation to split https://github.com/sebastianbergmann/phpunit-mock-objects from PHPUnit itself and move it to its own repository was to allow for a refactoring of the stub/mock code so that it could be used by other test frameworks. In all these years since the split this never happened. It is is safe to assume that it will not happen.

With that being the case, there is no advantage in having a separate repository/component that holds the test double library for PHPUnit. Therefore phpunit-mock-objects should be "merged back" into the PHPUnit repository. I would like to do so without losing the history that is in the https://github.com/sebastianbergmann/phpunit-mock-objects Git repository.

I do not know whether this is possible (bring phpunit-mock-objects back into PHPUnit's repository without losing history) and if it is then I do not know how. This would be an excellent opportunity for a Git expert to contribute to PHPUnit.

What I need is a series of Git commands that adds the contents of https://github.com/sebastianbergmann/phpunit-mock-objects (only master, no branches, no tags) into a top-level tmp directory in the https://github.com/sebastianbergmann/phpunit repository. I will git mv the files from said tmp directory to their correct target directories.

@sebastianbergmann sebastianbergmann added the type/enhancement A new idea that should be implemented label Apr 25, 2018
@kgilden
Copy link

kgilden commented Apr 25, 2018

It is indeed possible to merge multiple repositories in git. It's a little-known fact that git repositories can have multiple "initial commits".

I've followed https://stackoverflow.com/a/20974621/766120 with great success (notice that the answer is not the accepted one), because it keeps the history.

However, I have noticed that later searching for specific keywords from the history does not work very well (https://stackoverflow.com/a/2929502/766120). I guess the search only goes down one branch and fails to look through all of the other commits that were included from the other branch.

@jderusse
Copy link
Contributor

Here is a snippet we used to merge 3 subrepo in one. https://gist.github.com/mRoca/12e2b649158010ebd24a8fcea0f36000
Not sur if it's still accurate Ping @mRoca

@gingters
Copy link

I'm not a git expert, but I would try the following:

  • Create a new branch on the source repo and do the move to the temp directory there.
  • On the target repo, create a new remote pointing to the source repo, and fetch the new branch from there.
  • Then rebase that fetched branch within the target repo to where you want it to start from. That should work without conflicts when you don't have files at the same locations in both repos.
  • Then move your file to the correct positions
  • merge

@nealio82
Copy link

I did this last week to merge 5 python repos

  • In the new ‘master’ repo, create a new branch
  • git remote add [other-repo-name] [other-repo-uri]
  • git fetch [other-repo-name]
  • git pull [other-repo-name]/[other-repo-branch]
  • checkout master repo master branch
  • git merge [other-repo-name]/[other-repo-branch] —allow-unrelated-histories

@axiac
Copy link
Contributor

axiac commented Apr 25, 2018

I experienced a different situation where the project started as being hosted on Subversion and, at some point, the current version of the code was imported into Git as a new project. The development continued using the Git repo but several months and several hundred commits later I started missing the project history that was not imported from the Subversion repository.

After I converted the Subversion repo to a new Git repo I joined the two Git repos while keeping the commit dates and documented the entire process in this post: http://axiac.ro/blog/merging-git-repositories/

@sebastianbergmann
Copy link
Owner Author

Trying what @nealio82 suggested:

$ git clone git@github.com:sebastianbergmann/phpunit
Cloning into 'phpunit'...
remote: Counting objects: 74923, done.
remote: Compressing objects: 100% (37/37), done.
remote: Total 74923 (delta 28), reused 46 (delta 24), pack-reused 74862
Receiving objects: 100% (74923/74923), 26.14 MiB | 8.91 MiB/s, done.
Resolving deltas: 100% (47495/47495), done.
$ cd phpunit 
$ git checkout -b merge-mock-objects
Switched to a new branch 'merge-mock-objects'
$ git remote add phpunit-mock-objects git@github.com:sebastianbergmann/phpunit-mock-objects.git
$ git fetch phpunit-mock-objects
warning: no common commits
remote: Counting objects: 7670, done.
remote: Compressing objects: 100% (129/129), done.
remote: Total 7670 (delta 44), reused 142 (delta 33), pack-reused 7508
Receiving objects: 100% (7670/7670), 1.32 MiB | 2.22 MiB/s, done.
Resolving deltas: 100% (5164/5164), done.
From github.com:sebastianbergmann/phpunit-mock-objects
 * [new branch]          1.0        -> phpunit-mock-objects/1.0
 * [new branch]          1.1        -> phpunit-mock-objects/1.1
 * [new branch]          1.2        -> phpunit-mock-objects/1.2
 * [new branch]          2.0        -> phpunit-mock-objects/2.0
 * [new branch]          2.1        -> phpunit-mock-objects/2.1
 * [new branch]          2.2        -> phpunit-mock-objects/2.2
 * [new branch]          2.3        -> phpunit-mock-objects/2.3
 * [new branch]          3.0        -> phpunit-mock-objects/3.0
 * [new branch]          3.1        -> phpunit-mock-objects/3.1
 * [new branch]          3.4        -> phpunit-mock-objects/3.4
 * [new branch]          4.0        -> phpunit-mock-objects/4.0
 * [new branch]          5.0        -> phpunit-mock-objects/5.0
 * [new branch]          6.0        -> phpunit-mock-objects/6.0
 * [new branch]          master     -> phpunit-mock-objects/master
 * [new tag]             2.0.10     -> 2.0.10
 * [new tag]             2.3.8      -> 2.3.8
 * [new tag]             1.0.0RC2   -> 1.0.0RC2
 * [new tag]             1.0.0beta1 -> 1.0.0beta1
 * [new tag]             1.0.0beta2 -> 1.0.0beta2
 * [new tag]             1.0.3      -> 1.0.3
 * [new tag]             1.0.4      -> 1.0.4
 * [new tag]             1.0.5      -> 1.0.5
 * [new tag]             1.0.6      -> 1.0.6
 * [new tag]             1.0.7      -> 1.0.7
 * [new tag]             1.0.8      -> 1.0.8
 * [new tag]             1.0.9      -> 1.0.9
 * [new tag]             1.1.0RC1   -> 1.1.0RC1
 * [new tag]             1.1.0RC2   -> 1.1.0RC2
 * [new tag]             1.2.0RC1   -> 1.2.0RC1
 * [new tag]             1.2.0RC2   -> 1.2.0RC2
 * [new tag]             1.2.0RC3   -> 1.2.0RC3
 * [new tag]             1.2.0RC4   -> 1.2.0RC4
 * [new tag]             1.2.0RC5   -> 1.2.0RC5
 * [new tag]             1.2.3      -> 1.2.3
 * [new tag]             2.0.4      -> 2.0.4
 * [new tag]             2.0.5      -> 2.0.5
 * [new tag]             2.0.6      -> 2.0.6
 * [new tag]             2.0.7      -> 2.0.7
 * [new tag]             2.0.8      -> 2.0.8
 * [new tag]             2.0.9      -> 2.0.9
 * [new tag]             2.3.7      -> 2.3.7
$ git pull phpunit-mock-objects/master
fatal: 'phpunit-mock-objects/master' does not appear to be a git repository
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

When I do git pull phpunit-mock-objects master instead of git pull phpunit-mock-objects/master I get:

$ git pull phpunit-mock-objects master
From github.com:sebastianbergmann/phpunit-mock-objects
 * branch                master     -> FETCH_HEAD
fatal: refusing to merge unrelated histories

When I skip this step and jump ahead to the final merge operation then I get:

$ git merge phpunit-mock-objects/master --allow-unrelated-histories 
Auto-merging tests/bootstrap.php
CONFLICT (add/add): Merge conflict in tests/bootstrap.php
Auto-merging phpunit.xml
CONFLICT (add/add): Merge conflict in phpunit.xml
Auto-merging composer.json
CONFLICT (add/add): Merge conflict in composer.json
Auto-merging build.xml
CONFLICT (add/add): Merge conflict in build.xml
Auto-merging README.md
CONFLICT (add/add): Merge conflict in README.md
Auto-merging LICENSE
CONFLICT (add/add): Merge conflict in LICENSE
Auto-merging .travis.yml
CONFLICT (add/add): Merge conflict in .travis.yml
Auto-merging .php_cs.dist
CONFLICT (add/add): Merge conflict in .php_cs.dist
Auto-merging .gitignore
CONFLICT (add/add): Merge conflict in .gitignore
Auto-merging .github/stale.yml
CONFLICT (add/add): Merge conflict in .github/stale.yml
Auto-merging .github/ISSUE_TEMPLATE.md
CONFLICT (add/add): Merge conflict in .github/ISSUE_TEMPLATE.md
Auto-merging .gitattributes
CONFLICT (add/add): Merge conflict in .gitattributes
phpunit-mock-objects/master is not a valid attribute name: .gitattributes:8
Recorded preimage for '.gitattributes'
Recorded preimage for '.github/ISSUE_TEMPLATE.md'
Recorded preimage for '.github/stale.yml'
Recorded preimage for '.gitignore'
Recorded preimage for '.php_cs.dist'
Recorded preimage for '.travis.yml'
Recorded preimage for 'LICENSE'
Recorded preimage for 'README.md'
Recorded preimage for 'build.xml'
Recorded preimage for 'composer.json'
Recorded preimage for 'phpunit.xml'
Recorded preimage for 'tests/bootstrap.php'
Automatic merge failed; fix conflicts and then commit the result.

These conflicts are due to the fact that the (contents of the) phpunit-mock-objects repository is merged into the root directory of the phpunit repository instead of into a temporary directory (from where the files can be git mved to where they belong after the merge commit).

  • Do I really need the steps that do not work?
  • If so, how do I make them work?
  • How can I get the (contents of the) phpunit-mock-objects repository merged into a directory other than the root of the phpunit repository?
  • How do I get rid of the tags from the phpunit-mock-objects repository?

@axiac
Copy link
Contributor

axiac commented May 9, 2018

Hello Sebastian,

I wrote a script that rebases the history line of phpunit-mock-objects starting with commit ab3c85afe on top of commit 377f99ab9 of phpunit.

Commit 377f99ab9 is the last commit of phpunit that contains the code of phpunit-mock-objects.
Date and content of commit ab3c85afe make it the perfect candidate as the first commit of a new branch that contains only the phpunit-mock-objects files. The history of phpunit-mock-objects before this commit is not needed; the changes introduced by older commits are already included in the phpunit repo.

Th script copies all commits, including branches and their merges, then carefully restores their original author and commit information. It doesn't copy the branches that were not merged and the tags.

The result of running the script is commit f9f952b49. It is the copy of phpunit-mock-objects/master into the phpunit repository as the tip of the new mockobjects branch created by the script.

On top of what the script produced I created three new commits:

  • The first one moves the source code and tests of phpunit-mock-objects to the directories where they will finally land in phpunit. It also removes the files from the root directory; they used to define phpunit-mock-objects as a package but its carrier as a package is about to close.
  • The second commit merges phpunit/master into mockobjects and resolves the myriad of merge conflicts. Almost all files are in conflict because when the branches diverged, phpunit files were deleted from the mockobjects branch and vice-versa.
    Solving the conflicts is simple: check out each file from the branch where it belongs.
    There is only one duplicate file (tests/_files/Mockable.php; see the phpunit version and the phpunit-mock-objects version). They are very similar; I kept the version from phpunit-mock-objects.
  • The third commit makes the needed adjustments to let phpunit-mock-objects fit into phpunit. It removes phpunit-mock-objects from composer.json and puts its dependencies instead. It also updates phpunit.xml and adjusts the phpunit-mock-objects tests to run from their new location (the test files and their fixtures were moved on the first commit).

Please add axiac/phpunit as a remote to your local repo, fetch from it and inspect the commits of the mockobjects branch using a desktop Git client that draws a nice graph of the repo history.

The last three commits (and their explanations above) are also the answer to your question. "Transplanting" the history of phpunit-mock-objects into a branch of phpunit is not required; it comes as a bonus.

@sebastianbergmann
Copy link
Owner Author

Thank you so much, @axiac, for your work on this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type/enhancement A new idea that should be implemented
Projects
None yet
Development

No branches or pull requests

6 participants