I currently work in a startup where I lead, remotely, a team of five developers. Our code base in all hosted on a private GitHub repository. Since I’m CTO I gradually improved the way I manage the whole team and we have now reached a pretty good level of stability, productivity and autonomy. Every week we close approximately 20 issues, that are a mix of features, bug fixes and refactorings.
Use every feature of GitHub
GitHub has everything every developer and team leader need. Prepare your repository to be the perfect place to code without any hassle.
Issues have a title, but it’s not enough. Create the labels to help you categorize every single issue you have. The labels I use are roughly the following. Assign different colors for each group of them:
– Type: this instantly tells you if the issue is a new feature, a bug, a refactoring or just an improvement. Every single of them are very different from each other, so every issue can only be of one type;
– Section: create those labels to know which part of code/stack will be affected by the issue, for instance frontend or backend;
– Priority: you don’t need to assign the priority to every single issue but it’s very useful in particular for critical cases. Use high priority label to immediately let your developers know that there is something major to do before anything else;
– State: I use these labels for issues that are completed or very close to be, but that still need something that cannot be done immediately, for example a database column change or a script to run.
The issues will be your dev team tasks. The body of the issue must be clear, but not long, and needs action points that any developer can convert into code right away. A well made issue doesn’t create any long discussion, in fact it leave no space for doubts or comments at all. If it happens, it means that the issue is vague and you don’t even have it clear enough yet. Another important rule to follow is that the issue should be related to one single thing, whether it’s a bug, a feature or anything else. When creating a new issue for a bug, always add the exact steps to reproduce it and think about what could have caused it, without excluding any hypothesis. When creating a new issue for a feature, don’t rush, think about it deeply, describe the goal of the feature before anything else, try to predict all the parts of the stack that the feature will affect, describe every single action the user will be able to do once the feature is done.
Without exaggerating, the checklists are extremely useful inside the issues, expecially for features. Use them to split a feature into many small tasks, the smaller, the better. Thanks to the checklist, you can also track the progress of any issue and GitHub helps you even more, showing the progress in the issues list too.
Milestones are crucial to contain all the issues of the current sprint and so to tell your developers which are the tasks that needs to be done. I usually do single week sprints, so just five working days. The most common timebox is two weeks but I prefer one because the less code changes there are, the easiest the debugging will be. At the beginning of the sprint (I use monday morning) add to the milestone the issues that needs to be done before the end of the sprint. Don’t make the mistake to add too many issues inside a milestone, you can add more issues anytime as the days goes by if some developers are free. At the end of the sprint (I use friday evening) every issue of the milestone should be closed. If there is still some work to be completed, move the remaining issues to the next sprint, but prevent this action to become an habit.
When creating an issue, you don’t need to instantly assign one of your developers, but on the other side, every issue inside a milestone should always have an assignee. Before assigning an issue, think about who of your team may fit the best. Each of your developers created different parts of the application, so when assigning a feature, choose the person that created similar features in the past. When assigning a bug, choose the person that recently modified the part of code that may be affected. This way you increase the speed of which the features and the bugs are resolved since the ones that will work on them are already familiar with the code. But what about new developers? For them assign the easiest tasks available, so they get familiar with the application code, and as the time goes by, increase the complexity of their tasks. Before assigning tasks to new entries, it might be helpful to just tell them to play around with the existing code to see how things work.
Pull requests and code reviews
When your developers create a new Pull request, tell them to always assign you and another developers as a reviewer. I don’t think is necessary that more than two developers perform the review of a PR. I recommend to add in the body of the PR the number of the issue the PR is related to. In this way you will notice the reference to the PR inside the issue. After submitting a PR, first of all, the creator should quickly look at all the code that changed to see if they forgot something or not. Then you and another (optional) developer have to review the PR to approve or request changes. If another developer is assigned as a reviewer other that you, the PR creator should assign the one that they think is the most familiar with the code changed. Be strict as a reviewer so that your developers will gradually learn from their mistakes and the code quality will increase during time.
Putting it all together
As I already mentioned we use timeboxed iterations, called sprints. This is common for many software development methodologies, like Agile or Scrum. I won’t dive into these topics, but I’ll just describe how the flow of a single sprint looks like and how I manage it.
The first day of the week is where I add and assign most of the issues inside the current milestone. It’s very common that the current milestone already have some issues coming from the past milestones. This is important to note because I don’t start with an empty milestone every monday, and this day is not the only one that I use to add issues into milestones. It’s more something that happens gradually during the days of the week. For example in the past sprint, on thursday, I may add something to the next sprint because I already know that the issue cannot be done in the current sprint.
During the week the developers are working on the issues that I assigned to them (or that they self assigned). They don’t need to ask me what to do and when, everything is already on GitHub. The what and the how are the issues, the when is the milestone due date. Then the labels, like the priority one, will help them to prioritize a task over another.
During the week I usually review the pull requests, check the commits of my team as they come, work on some issue by myself, create new issues or join some calls.
The last day of the sprint is where I usually merge the pull requests into the main branch and where I test the app to see if everything look as expected. Of course every pull request should trigger some automatic tests too.
As I mentioned, monday is the day where I start the sprint, but it’s also the day where the sprint is ended and is time for the code to go into production.
We have seen that GitHub alone is a wonderful tool to manage everything you need for your developers. Any good and efficient management needs solid fundamentals and GitHub gives you all of them. When creating issues, so tasks, for your developers, always be clear, tidy and thoughtful. When adding tasks to a milestone, be realist and don’t try to predict everything exactly because you’ll fail and it’s worthless. When reviewing PRs, be strict but not too pedantic. Your developers need to learn from you but you are learning from them too.