How to Fork Mastodon
There has been a lot of grumbling lately about Gargron's actions as the project's "benevolent dictator for life", and the Florence project (previously known as "forktogether") is drawing attention for trying to fork the project and run it more democratically.
But how would someone go about forking a free software project as large as Mastodon? Surely it would take a Herculean effort to even get started?
That is where you are wrong! If you have some level of technical competence and prior knowledge of how to use the Git version control system, then creating the initial "downstream" fork and merging changes from Mastodon is the easier part of the project lifecycle. That is what this blog post is going to focus on.
The hard parts are figuring out project governance, attracting developers, software licensing, product branding, determining what makes your project different, juggling the competing demands of all your users, managing changes that break "upstream" code, defining what you want to include in each release and a whole host of other issues that would make your head explode.
However if you are just creating a fork for your own instance and only want to make minor or cosmetic changes to better tailor the experience for the community you are cultivating, your experience will be much more straightforward.
Grab the base code
If you decide to host your project on Gitlab because you don't like the fact Microsoft owns Github, or you want to host your code on your own server, then your first step would be to create a new repository in Gitlab and clone that empty repository to your computer.
The next step is to add Mastodon's repository as an upstream remote you can pull from:
$ git remote add upstream https://github.com/tootsuite/mastodon.git
Now you can grab a particular tagged version of Mastodon to base your fork on. For example, if you chose version 2.7.0 as the starting point you would run these commands:
$ git fetch upstream --tags $ git pull upstream v2.7.0 $ git push -u origin master
That fetches all the known tags from Mastodon's git repository, pulls a copy of the version that interested you, then overwrites the blank master branch on Gitlab.
If you wanted to keep the code on Github then you could just use the "fork" function through the browser-based GUI to complete this step, because the instructions above will be applied automatically. The key difference is that your fork would be based on today's master rather than a specific version tag unless you specify it.
Customise the fork
One of the first things you will want to do is setup an automated build system for your code. If you are using Github you can skip that step as it will already be set up, but for Gitlab users you will need to create a new branch, add a known-good build configuration and then add it to your fork:
$ git checkout -b gitlabci $ wget https://framagit.org/luc/mastodon/blob/gitlab-ci/.gitlab-ci.yml $ git commit .gitlab-ci.yml -m "Added CI script" $ git push
You should then create a merge request in Gitlab and use this to merge the change into the master branch. The reason it is better to do this through the website rather than the command line is it makes your changes easier to review later by potential project contributors.
Next you will want to ensure the documentation is updated to reflect that this is your fork and not a carbon copy of the official Mastodon project. Once again you should create a branch, commit your changes to it, push them to the server and then raise a merge request to add them to the master branch.
To ensure that the automated build tools pull assets and code from your fork and not the mainline project, you will also run a find and replace on all files and replace the Mastodon project's Github repository URL with your fork's git repository URL. If you are not comfortable doing this with the command line, you can use the search and replace function in the Atom text editor.
Finally, you will want to remove branding from the application itself and replace it with your own! In some cases, this will involve editing the build scripts so they say your fork's name instead of "Mastodon", but most of your work will involve editing files in the "app" and "config" folders. Do not try to do an automated search and replace for this as you may break the underlying code and build tools.
Wait... is that it?
Technically, yes! At this point you could release the application as the "version 1.0" of your fork:
$ git checkout master $ git tag v1.0.0 -m "The first ever release of my fork"
However, it is doubtful anyone will be impressed enough with your changes to prefer it over the upstream version of Mastodon, as you are not adding anything particularly interesting to it. You also have no mechanism for adding updates from the upstream project, which has far more resources and developer attention.
Merge upstream changes
Regardless of whether you are hosting the project on Github or Gitlab, the process for shifting from 2.7.0 to 2.7.1 would be the same:
$ git checkout -b v2.7.1 $ git pull upstream v2.7.1
If you are very lucky, that will work without incident. But it is more likely that you will have merge conflicts to resolve. Fortunately, you can simply edit the files in a text editor and then run git commit -a filename.ext on each of them to mark it as resolved.
Once you are satisfied with your changes, you should raise a merge request and create a pipeline that builds that branch. This gives you some assurance that the project will build as expected and continue to pass tests. You may also have to edit the .gitlab-ci file to accommodate the new changes.
This is also the stage where you can decide to remove changes you do not like. The easiest way to do this is to make changes yourself as new commits, but you can also run git revert on individual files or commit tags.
When you are satisfied with your changes, you can then merge the changes into your master branch and see if it builds. If it triggers more merge conflicts, you will need to resolve those in the branch you just created and then try again until it works.
It is not compulsory, but it is recommended at this point that you build and run the code in master branch in a test setup yourself to make sure it runs the way you expect it to and has the new upstream features that you were expecting.
Make new changes
For every code change you want to make, simply create a branch with an accompanying merge request, then keep committing changes until you are ready to merge.
If other people can see your merge request, they may check out the branch and make their own helpful contributions. Or they may just make suggestions in the comments section that you can agree or disagree with. Creating a roadmap in the project wiki and populating the CONTRIBUTING.MD file will help communicate your plans better.
Over to you
This blog post just explains how to get started with a new fork of a popular free software project. As with any such endeavour there is no guarantee of success, and there is no obligation on anyone else to use your fork. Also, there is an assumption that you are technically-competent enough to make code changes, use version control effectively, and have the time and resources to manage a software project when it gets popular.
The most likely outcome is that you will be the only person using and developing your fork. But if you are only making minor cosmetic changes for your instance and the community that runs on it, that may be enough for you to achieve your objectives.
In the even you implement something particularly interesting you may be asked to contribute your changes back to the original project. In which case you can use Github's own internal mechanisms, or you can ask the project to create a feature branch for you and then push your downstream changes to it.
If this all seems like too much effort, you can take your chances and make feature suggestions directly with the upstream Mastodon project itself. Be aware that your idea may not be picked up by an interested developer, and it could take months or even years before it is finally implemented.
Final note: Mirror the repository
It might be that all you want to do is make an automatically updating mirror of the Mastodon project on a separate Gitlab instance for posterity. You can configure that instance to do this using just the browser-based GUI by following these instructions: https://docs.gitlab.com/ee/workflow/repository_mirroring.html.