>
Artificial Intelligence

GitHub is four skills pretending to be one

I have been on GitHub since 2013 and I have taught four coworkers how to use it for the first time. The thing I keep relearning is that “using GitHub” is not one skill. It is at least four skills: cloning a repository, making a branch, opening a pull request, and using Issues to track work. The first three are about code. The fourth is about project management, and the project management part is the one that most beginners stall on, because GitHub’s issue and project tooling is a separate mental model from the git command line. I am going to walk through the four skills in the order I wish someone had walked me through them, with a focus on the issue and project workflow that turns GitHub from a code-hosting service into a place where a small team can actually coordinate.

This is for the developer who has used git locally, has pushed a commit or two to GitHub, and is now trying to figure out why the Issues tab looks the way it does. It is also for the small-team lead who has inherited a GitHub repository and a team that does not know how to file a bug, and is trying to set up a workflow that does not require a project manager. I am going to assume you have the GitHub CLI (a command-line tool for talking to GitHub from your terminal) installed, and that you have authenticated with gh auth login. The CLI is the cleanest way to do the issue workflow, and the team members I have onboarded with the CLI have stuck with it longer than the team members I have onboarded with the web UI.

The issue is the smallest unit of work

The thing I wish someone had told me is that an Issue is not a bug report. An Issue is a unit of work that can be a bug, a feature request, a question, a design proposal, or a tracking entry for something that is not yet ready to be a pull request. The label (a colored tag you can apply to an issue to categorize it) is what tells the team which kind of work the issue represents. A team that uses labels consistently can scan a list of issues and know what is what. A team that does not use labels gets a list of issues that all look the same and cannot be triaged (sorted and prioritized).

The labels I have landed on for a small team of three to six developers:

  • bug for confirmed bugs, with a clear reproduction (the exact steps someone took to make the bug happen)
  • feature for new functionality that has been agreed on
  • proposal for ideas that have not been agreed on yet
  • question for issues that are really a developer asking how something works
  • chore for maintenance work that is not a bug or a feature (renaming a function, updating a dependency)
  • blocked for issues that cannot move forward without something else happening first

Labels are also what makes the issue filterable. The Issues tab in the GitHub web UI has a filter bar at the top. Click the bar, pick a label, and the list narrows. The CLI equivalent is gh issue list --label bug. A team that uses labels consistently can pull a list of “every confirmed bug that is not blocked” with one command. A team that does not use labels has to read every issue to know which is which.

Issues are not the only artifact either. Discussions are for conversations that do not have a clear owner or a clear next step. The “Ideas” category in Discussions is for feature proposals that the team has not agreed to work on. The “Q&A” category is for questions about how the code works. The “General” category is for everything else. The mistake I see small teams make is filing every conversation as an Issue, which turns the Issues list into a mess of half-conversations and half-tasks. Use Issues for tasks. Use Discussions for conversations.

The pull request is not the same as the issue

The second piece of mental model is the difference between a pull request and an issue. An issue is a unit of work that needs to happen. A pull request is a proposed change to the code that addresses one or more issues. The connection between the two is the “closes #123” syntax (a phrase you write in the PR description that automatically closes issue #123 when the PR is merged). When you write Closes #123 in a pull request description, GitHub automatically closes the linked issue when the pull request is merged. The linked issue gets a “closed by” reference, and the issue’s timeline shows the merge event.

Workflow on a small team looks like this. The team lead or a developer files an issue with a clear description and a label. A developer picks up the issue by self-assigning (clicking the “Assign yourself” link on the issue page) or by being assigned by the lead. The developer creates a branch (a separate copy of the code for the developer to work in without affecting the main code), makes the change, and opens a pull request that references the issue with Closes #123. The team reviews the PR, requests changes if needed, and approves it. When the PR is merged, the issue is closed automatically. The whole loop is visible on the issue’s timeline, and the team’s velocity (how quickly work moves from “filed” to “shipped”) is measurable from the issue list.

Common mistake is treating the pull request as the only artifact. The team reviews PRs, but the issues that the PRs are supposed to close are still open, because nobody went back to close them. The fix is the Closes #123 syntax in every PR description. The fix is also a CI (continuous integration) check that fails the PR if the description does not reference an issue. The CI check is optional, but it is the cleanest way to enforce the discipline on a team that does not have a project manager to nag people.

The project board is the dashboard

Project boards are the dashboard. A Project is a board with columns, and each column is a status. The default columns are “To do,” “In progress,” and “Done.” You can add custom columns. The cards in the columns are issues and pull requests. Drag a card from “To do” to “In progress” when work starts. Drag from “In progress” to “Done” when the work merges and the issue closes. The board is the team’s shared view of “what is being worked on right now.”

Another common mistake is treating the Project board as the only source of truth. The team keeps the board updated, but the Issues tab is a mess, because the issues do not have labels, do not have assignees, and do not have clear descriptions. The board is a view, not a database. The Issues tab is the database. A team that keeps the Issues tab clean can rebuild the board from a filter. A team that keeps only the board clean has a board that looks fine and an Issues tab that is unsalvageable.

The board feature I have found most useful is the “automated” column rules. You can set a rule that says “when an issue is labeled bug, move it to the To do column.” You can set a rule that says “when a pull request is opened against the issue, move the issue to the In progress column.” The rules save the team from manually dragging cards. The rules also keep the board honest: a card in the “In progress” column should have a linked pull request, and the rule enforces that.

The CLI is faster than the web UI for the issue workflow

The fourth piece of mental model is the CLI. The gh (GitHub CLI) command is faster than the web UI for the issue workflow, and the team members I have onboarded with the CLI have stuck with it longer. The commands I use most:

  • gh issue create opens an issue from the command line, with --title and --body flags for the title and description, and --label and --assignee flags for the metadata
  • gh issue list lists issues, with --label, --assignee, and --state flags for filtering
  • gh issue view 123 shows the full issue, including the timeline, in the terminal
  • gh pr create opens a pull request from the command line, with --title, --body, and --base flags for the metadata
  • gh pr list lists pull requests, with the same flag pattern as gh issue list
  • gh pr checkout 456 checks out the branch for pull request 456 locally, so you can review or test the change

The CLI is the right tool for a developer who is already in the terminal, and the workflow is faster than clicking through the web UI. The web UI is the right tool for a non-developer team member who is filing a bug or asking a question, and the team should not try to force non-developers onto the CLI. The mistake I see small teams make is forcing everyone onto the CLI, which makes the issue workflow feel like work and discourages non-developer team members from filing issues at all.

What I would tell past me

If I could send a message back to the version of me that was teaching my first coworker how to use GitHub in 2015, I would say three things.

  • An Issue is a unit of work, not a bug report. Use labels to tell the team which kind of work the issue represents. The team that uses labels consistently can scan a list of issues in 30 seconds. The team that does not use labels reads every issue to know which is which.
  • A pull request is not the same as an issue, and the connection between them is the Closes #123 syntax. Use the syntax in every PR description. The CI check that fails the PR if the description does not reference an issue is the cleanest way to enforce the discipline on a team that does not have a project manager.
  • The Project board is a view, not a database. Keep the Issues tab clean, and the board can be rebuilt from a filter. Keep only the board clean, and the Issues tab is unsalvageable. The team that keeps the database clean can change the view as needed.

Trade-offs

GitHub is not the only option, and the team that picks GitHub for the project management workflow is picking a specific feature set. GitLab has a similar issue and project workflow, and the labels and project boards work the same way. Jira (a paid project management tool made by Atlassian, separate from any code host) has a more powerful project management feature set, but the cost is real (about $8 per user per month for the team tier) and the integration with git is bolted on rather than native. Linear (a paid project management tool aimed at software teams) is a popular alternative for teams that want a faster UI and do not want to use the GitHub Issues tab. The trade-off with Linear is that the issues and the code live in different places, and the connection between them is a third-party integration. The trade-off with GitHub Issues is that the project management feature set is good enough for small teams, the cost is free, and the integration with git is native.

Time is the first real cost. Setting up the label scheme, the project board, and the CLI workflow takes about a day for a small team, and the first month of using the workflow is going to feel slower than the workflow it replaced (which is usually “we just talk about it in Slack”). The slack cost is real for the first month. The long-term cost is lower than the cost of the Slack-only workflow, because the issue list is searchable, the timeline is preserved, and the team does not have to re-derive context from a chat scrollback (the archive of old messages in a chat channel). A team that gives the workflow two months before deciding it is not working is going to stick with it. A team that gives up after two weeks goes back to Slack, and the issues pile up as unread.

Features are the second cost, and the one that is going to get better. GitHub Projects is in active development, and the feature set is improving every quarter. The new “Insights” tab in Projects gives the team a velocity chart (a graph of how much work the team completes per week) and a burndown chart (a graph showing whether the team is on track to finish a set of issues by a deadline) without leaving GitHub. The roadmap is moving toward tighter integration with GitHub Actions (GitHub’s built-in CI/CD, or continuous integration and deployment, system), which means a future workflow could close an issue when the CI pipeline passes. The trade is that the team is betting on GitHub’s roadmap, and the bet is not free if the team has already invested in a third-party project management tool.

Leave a comment