-
Notifications
You must be signed in to change notification settings - Fork 33
Workflow
By now you should have read Getting started and the introduction of Getting involved; you should already have forked and cloned this repository and you should be watching it (don't "unwatch" it as the GitHub tutorial suggests!).
As you read through the page, you'll find that branches and issues are mentioned very often. For a visual illustration of our branches, open the network graph; for concrete examples of issues, open the issue tracker. Keep those pages within mousereach while you read this page, just in case you'll want to have a look at them.
All Git examples below assume that your working directory is $RED_SPIDER_ROOT
.
The first time before you start doing work on the Red Spider Project, you might want to run git config -e
and paste the following lines in the configuration file, then save:
[branch "master"] remote = upstream merge = refs/heads/master
This ensures that when you do
git checkout master git pull
You'll automatically receive the latest changes on upstream/master
, i.e. the master branch of the central repository (a.k.a. the integration branch). Of course this assumes that you added the central repository (the one this wiki belongs to) as the "upstream" remote, as explained in the GitHub forking tutorial. The remainder of this section assumes that you have done the latter and that you also added the above configuration lines.
Whenever you start working on a new topic, such as a feature, a redesign or a new program, you create a new branch with a name that hints at the topic. For example when you're going to factor out duplicate code in your spaghettimonster
command, you could call the branch spaghettimonster-refactor
:
git checkout master git pull git checkout -b spaghettimonster-refactor
The last command is the one that actually creates the branch. You first checkout master because that's where you want you topic branch to split off, and you do the pull in between to make sure that you start your new branch with an up-to-date version of the project software.
It's fine to have multiple topic branches in parallel. For example one for factoring out your spaghettimonster
, one for adding achievements to your tic-tac-toe game and one for trying out an idea that you have for setup.py. In fact, part of the reason that branches were invented is that they help you work on multiple things at the same time!
For now, we'll assume that you're working on spaghettimonster-refactor
.
Try to commit "atomic" units of work. For example, you can commit "Factor out the spaghetti winding pattern" separately from "Create the Spaghetti class". This isn't a very strict rule, though; especially when you're adding a program (or something else, such as a SVG file) that you created before, naturally you don't have to cut it into little commits first.
As a rule of thumb, new source files go directly into the src
directory, not in a subdirectory. Only create a subdirectory if your program consists of many source files. See Project directory overview for more information.
Whenever you create a new source file, you should introduce a comment section at the top stating that you hold the copyright. It should also refer to the Red Spider Project License. Check the minimal requirements for an example.
If you work on a source file that somebody else created and you're contributing to the program logic, you should add your name to the copyright statement. If you're not contributing to the program logic you may either add a "minor contributions by..." line, or add your name to the Authors.txt file if you didn't do that yet.
SVG files, and possibly other file types that are based on markup languages, may contain special sections that are meant for copyright information (Inkscape is known to let you access that section). Use those sections.
In all other cases where you edit a file, add your name to the Authors.txt.
The first time that you push your branch you might have to specify its name explicitly, like this: git push spaghettimonster-refactor
. After that you can just git push
. Protip: if you run git config --global push.default current
, a bare git push
will always mean "push the current branch to origin", whether you pushed it before or not. Another protip: git push --all --prune
will bring your public fork entirely up-to-date with your private repo. But don't do the latter if your private repo holds commits that you might want to rebase or reorder, changing history after publishing is a bad idea!
There are many reasons why you might want to push. For example:
- because you need help (see below);
- because your hacking day is over and you like to have a remote backup;
- because you like to show off what you've accomplished so far;
- because you're collaborating with somebody else (see Collaboration);
- because you're finished working on the topic and you're going to do a pull request (see further below).
Perhaps you can't get a piece of code to work, or perhaps you do get it to work but you're wondering whether it works on other platforms as well. You might also get in trouble because somebody else's command is not behaving as you expect. Whatever is your problem, the way to get help is to create a new issue. The issue tracker is like our dedicated forum for discussing concrete work that needs to be done.
Make sure to
- choose a descriptive title, e.g. "please test whether spaghetti winding works on Windows";
- mention your branch either in the title or in the message, e.g. "yourgithubname/spaghettimonster-refactor";
- explain your problem or your motivation for the work you're doing;
- precisely describe what steps lead to the problem, if your problem is a bug;
- clearly describe what you're trying to achieve, if you can't get something to work;
- explain very precisely how to test your work, if that is what you ask for.
If your program is run from within rsshell (which it should be, in most cases), then you have a convenient environment at your disposal that you should use to your advantage. In particular, you can
- call other Red Spider commands by their names, without needing to specify where they are;
- use Red Spider headers and libraries (such as
xkcd-fetch
andlevel_up
) without needing to specify where they are; - obtain the path to the project root directory without needing to figure out where it is by yourself.
If you don't do anything, your source files will just sit in the src
directory. Users who run rsshell and who don't actively seek out the source files -- as they're not aware that there's hidden treasure in there -- will not automagically be able to run them by just typing spaghettimonster
.
Your options are:
- Edit setup.py so it will install your command (if your program is written in Python or if you're clever enough to figure out how to have setup.py do the same thing for other interpreted languages).
- Create a build file (makefile, jamfile, SCons file...) in the
src
directory with the same name as your program, which puts any intermediate build products in thebuild
directory and installs the executable in thebin
directory (see also Project directory overview). In this case you still need to edit setup.py so that it will run your build file. - If neither of the above options is feasible, create a text file in the
doc
directory that explains how to build your program. Add a line to thefarewell_msg
in setup.py to notify users about the build documentation. - Have somebody help you. So that means push your branch and submit an issue!
Suppose that, while working on spaghettimonster-refactor
, you get a very exciting idea and you wonder whether it could work. No problem. After your next clean commit, just split off another branch: git checkout -b spaghettimonster-coolexperiment
. Try out your idea, saving commits along the way. If at some point you decide that you want to keep the changes and use them in your main topic branch, just merge the experimental branch back into it:
git checkout spaghettimonster-refactor git merge spaghettimonster-coolexperiment git branch -d spaghettimonster-coolexperiment
Alternatively, you may just abandon the experimental branch if it doesn't work out the way you hoped for. Perhaps it may come in handy later, in which case you could rebase the branch on your then-current topic. If you're very disappointed you can also delete the branch (without tagging its head first) so the commits will be deleted on the next garbage collection.
It could go the other way round as well. If you decide that you like your work on spaghettimonster-coolexperiment
and that it obviates spaghettimonster-refactor
, you can abandon the latter and work towards a pull request for spaghettimonster-coolexperiment
instead.
Make sure that people can use your stuff without needing to understand how it works. Preferably your program should have a short usage message which is displayed when you run it with the -h
flag, and a longer explanation in a .txt
file in $RED_SPIDER_ROOT/doc
. If your program considers -h
and --help
to be different things (it doesn't if you use Python's argparse
) then --help
should preferably just print the file in /doc
. If you wrote a library, definitely explain it with a file in /doc
. The files in /doc
are usually displayed by rshelp. You can write anything you want in your documentation files; make it funny if you like.
Depending on what you've done, you may need to update Readme.md or Dependencies.md. For example, if you're the first to contribute a Haskell program, you'll have to add Haskell to the list of programming languages in Dependencies.md.
If you edited any markdown file (Readme, Dependencies or whatever), the first thing you should check after pushing your branch is whether the markdown renders correctly. To do so, go to your GitHub fork, pick your branch from the dropdown menu and navigate to the relevant markdown file(s).
Here comes the exciting stuff! When you're done working on your topic, push the branch to your fork and do a pull request. The head branch is your topic branch, e.g. spaghettimonster-refactor
. The base repository is the-xkcd-community/the-red-spider-project and the base branch is master, but those should be selected automatically.
When you do a pull request, what you're actually asking for is that your branch will be merged into the integration branch (i.e. the-xkcd-community/master). In other words, what you're saying is "my work seems done, let's make it truly part of the project!". But before that can happen we first need to do some checks, which is why a pull request also appears on the issue list.
In particular, when you do a pull request we'll want to check that
- your stuff meets the minimal requirements;
- everything that's supposed to work works on all supported platforms.
To help your pull request get handled as switfly as possible, follow all the rules that also apply for any other issue (see above). In particular, make sure that the title includes a very short description of the topic and that it states which platforms still need testing, if any. For an example of a pull request, consider #15.
After your pull request is granted, you live in the peculiar situation that the central repository has your branch merged into master but your own private repo and public fork don't. You fix that with the following commands:
git checkout master git pull git branch -d spaghettimonster-refactor git push --prune
Note that you remove the spaghettimonster-refactor
branch. Your work on that topic is done, so you'll just create a new topic branch if you're going to work on spaghettimonster
again.
You might also want to pull in master for other reasons at other points during your workflow. Especially if you created your topic branch long ago, you might want to merge the latest state of the integration branch into it. For example because it helps you work with the latest state of the project, or because you want to take advantage of cool stuff that was merged in the meanwhile. To do it, just make sure that your working topic branch is clean (i.e. commit after any edits that are still pending), then run git pull upstream master
.
Others need help too! So watch this repository, and when a new issue appears, please consider whether you might be able to help.
By "collaboration", we here mean "two or more people working on the same topic branch". There are two main approaches.
Approach 1: each collaborator pushes to their own public fork. One collaborator keeps the "central version" of the branch; that collaborator pulls in all the work of the others from their public forks. The others then pull in that central version to their private repos in order to get up-to-date again. This may work through pull requests just like with the topic branches and the integration branch.
Approach 2: one collaborator gives write access to their public fork to the others. Everyone pushes to and pulls from the same public repository.
The advantage of approach 2 is that it is more direct than approach 1 and that no single person has the responsibility to keep everything together. The disadvantage is that it doesn't work very well when activity is high or when many collaborators are involved. Approach 1 also offers more redundancy and doesn't require anyone to set up special permissions for their public fork.
Apart from the technical details with regard to branching, you'll have to agree with your collaborators on who does what. You may want to create a milestone (or request that it be made); see the milestone list for examples. Your personal workflow remains the same otherwise.
The whole of activities going on in and around our repository is a complex of cycles within cycles within cycles. The innermost cycle is the iterative committing of small changes. Each edit brings the working directory of the author out of sync with their private repository, each commit brings the repository up-to-date again.
The middle cycle is a chaotic mess at the scale of one or a few topic branches: they get pushed, they get tested, they may occasionally pull in master, they may have satellite branches for experimentation and large subtopics, and they may be pushed and pulled back and forth between collaborators. The opening and closing of issues belongs to this scale as well.
The outermost cycle works at the scale of the entire project. Somebody starts a new branch to work on a topic. After a while the topic is done and the author(s) issue a pull request. Other project members react to the pull request and help to verify that everything is in order; some final polishing might need to be done. Finally when the pull request is granted, the topic branch is merged into master and the cycle repeats. Multiple topic branches from different team members might be going through this cycle at different stages, simultaneously.
There's something deep about that final merge. From the moment that the branches went apart, either has been receiving changes that the other didn't. The topic branch accumulated topic-related work while the integration branch collected the results of other topic branches. Through the merge, a commit is created which is up-to-date with the state of both. That single commit, living on the integration branch, is holding the entire project until somebody pushes again. Consider that while you watch the network graph!