Good for Open Source/Multi-contributor projects
- Overview
- Step Details
- Important Details/Warnings
- Upstream: The original, organization-based repo (e.g. fsu-acm/contest-suite).
- Origin: The remote Github repository of one person (e.g. andrewsosa/contest-suite).
- Fork: Creating a copy of a repository while maintaining association.
- Pull Request: Github-specific feature for merging accross Github repositories
The steps of the process are as follows:
- Fork the Upstream
- Create a working branch
- Commit your changes.
- Pull Request your fork to the upstream
- Update your master to the upstream's master
goto 2
The goal of this workflow is to create a cyclical flow of changes. Each contributor's own master branch represents a mirror of the upstream's, which is used for keeping the working versions up to date in the event the upstream changes.
When working on open-source/multi-contributor projects, each project member should have their own copy of the repository associated with their Github account. The only exception would be if two people are working very closely on implementing the same changes, in which case they can work off one of their forks.
These branches are typically associated with a specfic additional feature, but in cases where there's a significant rewrite of the project, the entire rewrite can be on one branch. These feature branches should be specifically named, such as "add-admin-account", "remove-user-profile", "patch-captization-bug".
Do not work on your master branch.
Make your commits. Commits should typically be as close to atomic as possible, i.e. you want to commit your changes in the smallest increments that logically make sense. If you add some new files, that's a commit. If you make a change specific to one file, that's a commit. If you change a whole bunch of files at once, commit them togther. Commit's don't need to each be a working copy of the project, but should represent incremental steps in development. However, the final commit before merging back into the upstream should be functional.
Also, do not work on the master branch. You want to always have a mirror to the upstream. If the upstream master changes while you are developing, you can take the following steps to make sure you have an up-to-date copy to work on:
- Fast forward your master branch to the upstream's master.
- Rebase your working branch onto your updated master.
This is how your changes get incorporated into the project. You can create your pull request, which will try and merge on Github the changes on your change branch back into the upstream master. Make sure you've pushed your changes to your own repo first.
Typically during the PR process any continuous integration (CI) will run on your pull request, so it will check for things like passing tests, making sure the build runs, or the code style matches project standards.
Finally, if you make more commits to your development branch, your Pull Request will automatically be updated to include those changes.
Also, request reviewers from fellow maintainers -- code review is a real thing, and it really does matter.
Once your changes from the PR are accepted into the upstream master branch, you can update your fork's master branch. Do not merge your development branch into your master locally. This will screw up the Git tree and create havok for everyone.
Usually you can just delete your working branch, or you when you perform the pull Git will automatically recognize that the branch was merged.
Now, you don't need to create a new fork every time. You already have a copy of the repo, and new development branches can come from your updated master branch.
These are the most important things to watch out for, as touched on earlier in this guide:
This always seems like a minor detail, but it has the highest potential to wreck the commit graph for the whole project. Having a perfect mirror of the upstream master is absolutely critical for staying up-to-date with other contributor's changes.
Again, this is another great way to screw up the commit graph for the whole project. If Github is merging the branches, that creates a commit. If you merge the branches, that creates another commit. These commits are not the same commits, and everyone will see what you've done.
This one is a bit more obvious -- once you have a copy of the repository, you don't need another one. Heck, Github won't let you make another one without deleting the one you already have. Just make sure you update your master.
Basically, if the project gets new changes while you're working and you don't update your copy to have these new changes, this will cause merge conflicts when you try and reincorporate the changes. Rebase is hard, but you need to learn how to use it.
Good IDE tools (IDEA products, VSCode, Atom) have good extensions to make things easier on fixing merge conflicts which may arise from Rebases.
Sort version: Don't do this.
Long version: If you're the primary project maintainer, and you know what you're doing, and you're only making small changes like updating the readme, maybe it's okay to commit directly. Just make sure everyone on the project knows to update their master before doing anything. If you're actually making real changes, make a branch you dummy.
The main thing is that communication is key. Follow the guidelines, make sure your fellow contributors follow them, and make sure you're communicating with your contributors.