Which Tools Link Code Commits to Tasks?

Most tools that link commits to tasks read an ID out of the commit message. A few use branch names, and some do it from the IDE. Here is how each approach works, what it needs from your team, and what the link is actually good for.

Most project tools can link a commit to a task. GitHub, GitLab, Jira, Linear, Azure Boards, Redmine and YouTrack all do it by reading a task ID out of the commit message, such as #123, PROJ-123 or AB#123. Linear can also link work through the branch name. IDE-based tools such as Vi do it the other way round: you finish a task in your editor, and the tool writes the commit for you with the task ID already in it.

All three approaches work. They differ in what they ask of developers, how they fail, and what you can do with the link afterwards.

Why the link is worth having

The obvious reason is traceability: six months from now, someone looks at a line of code and wants to know why it changed. The link answers that.

There are two less obvious reasons, and they matter more day to day.

For a manager, the link replaces a status report. When commits are attached to tasks, the task itself shows what happened: which commits, which files changed, how many lines, on which branch, by whom. Nobody has to write "done, changed the invoice module" in a comment or explain it in a stand-up.

For a customer, the link is the middle of the story. If a task started as a customer's email, the commit is the point where their request turned into real code. What the customer cares about is the end of that story: a clear "this is done" message once the work has actually passed review and shipped, not when the first commit lands. That is what closing the loop means in support, and commit linking is one piece of it.

Three ways a commit gets linked to a task

1. An ID in the commit message

This is the oldest and most common method. You type the task key somewhere in the message:

Fix rounding in invoice totals, refs #482

When the commit is pushed, the tracker scans the message, finds #482 and attaches the commit to that task. Some tools also accept a keyword that changes the task's status, such as Fixes #482 or Closes #482.

It costs nothing to adopt and works from any Git client. The weak point is that it depends on people remembering. A missing or mistyped ID doesn't produce an error. The commit just never shows up on the task, and nobody finds out until someone goes looking.

2. An ID in the branch name

Here the link happens one level up. You create a branch called something like eng-482-invoice-rounding, and every pull request from that branch is linked to issue ENG-482. Linear is the best-known example.

This is easier to remember than tagging every commit, because you name a branch once. It fits teams that review everything through pull requests, and helps less if your team commits directly to the main branch.

3. The commit comes from the task

In this approach you don't write the ID at all. You start a task from your IDE, do the work, and mark it done. The tool creates the commit with the task ID in it, pushes it, and moves the task on. Nothing has to be remembered, because nobody types the link.

How the common tools handle it

The details below can vary with the type of integration and your project settings, so each section links to the tool's own documentation.

GitHub

If a commit message mentions an issue number like #482, GitHub shows that commit in the issue's timeline once it is pushed. Closing keywords such as fixes, closes or resolves before the number, in a pull request description or a commit message, close the issue when the change reaches the default branch. No setup is needed, but the issue and the code have to live on GitHub. (GitHub docs)

GitLab

GitLab works much the same way. Mentioning #482 in a commit adds a note to the issue, and closing patterns like Closes #482 in a commit message or merge request description close the issue when the change lands in the default branch. The closing pattern can be changed. (GitLab docs)

Jira (Smart Commits)

Jira links any commit whose message contains an issue key such as PROJ-482, once a repository integration is connected. Smart Commits go further, with three commands you can put on the same line:

PROJ-482 #time 2h #comment Fixed rounding in totals #resolve

#comment adds a comment, #time logs work, and #<transition> moves the issue through the workflow. Two details catch teams out. The commit author's email has to match a Jira user who has permission to do the action, otherwise the command is silently skipped. And the whole command has to fit on one line. (Atlassian docs)

Linear

Linear links a pull request when the issue ID is in the branch name or the PR title. For other cases, such as several PRs for one issue or a PR that already exists, you use a "magic word" with the ID, like closes ENG-482, in the PR description or commit message. Linking individual commits is a separate setting that an admin turns on, together with a webhook in GitHub. With the integration in place, Linear can move the issue to In Progress when the branch is pushed and to Done when the work is merged. (Linear docs)

Azure Boards

For GitHub repositories, Azure Boards uses the AB# prefix: AB#482 in a commit message, or in a pull request description, links that work item. Fixes AB#482 can also move it to a resolved state. Mentions in a PR title or a comment don't create a link, and the Boards project has to be connected to the repository first. (Microsoft docs)

Redmine

Redmine reads commits from a repository it can reach and scans the messages for keywords set by an administrator. By default refs #482 links a commit, and "fixing" keywords such as fixes #482 can also change the issue's status. Because Redmine fetches the repository itself, the server needs access to your Git host. (Redmine docs)

YouTrack

YouTrack's VCS integrations link commits that mention an issue ID, and can apply YouTrack commands written after the ID, for example to change a state. Like Jira, the commit author has to match a YouTrack account for the command to run. (JetBrains docs)

Vi

Vi uses the third approach. Its IDE extensions show your tasks inside the editor. You press Start on a task, write the code, and press Done. Vi then:

  1. asks which changed files belong to this task (staged files are selected by default),
  2. commits them with the message [#482] Task title,
  3. pushes, if the repository has a remote,
  4. marks your workflow step as finished and moves the task to the next step, such as review or QA.

If the push fails, the task stays where it is, so the next person never picks up work whose code isn't on the remote yet. All Git commands run on the developer's machine. Vi keeps the commit details, not the source code.

On the task card, a manager sees each commit with its branch, author, line counts and the changed files (or just how many, if the workspace keeps file names private), without asking anyone for a summary.

Why doesn't a commit from the terminal move the task? Because Git only records code. It knows nothing about review steps, approvals or who works on the task next, so a commit is not a reliable signal that a step is finished. In Vi, a plain commit stays a plain commit, and the task moves when the developer says the work is done.

When the task came from a customer request, the chain continues past the commit. The request arrives by email or through a portal and becomes a task. The developer finishes it in the IDE, and the work goes through whatever review your workflow defines. When the task passes the last step, the customer gets the "done" message. Nobody has to remember to write it.

Where commit linking breaks in practice

Whichever tool you use, the same few problems come up:

  • Typos in the key. PROJ-428 instead of PROJ-482 links the wrong task without any warning. Message-based linking can't tell a mistake from a real link.
  • The commit isn't pushed. Nothing happens until the commit reaches the server the tracker watches. A local commit that never gets pushed leaves the task looking untouched.
  • Rewritten history. Squash merges and rebases replace the original commits. If the task ID was only in one of the small commits and not in the final message, the link can disappear.
  • Mismatched identities. Any tool that maps commits to people needs the Git author email or username to match an account.
  • Status moves on merge, not on review. A closing keyword marks the task done the moment code lands. If your team still needs QA or a sign-off afterwards, either avoid closing keywords or use a workflow that has those steps after the code step. The same applies to the customer: telling them "fixed" at merge time can be premature.

How to choose

If your code and issues already live in GitHub or GitLab and the team is disciplined about commit messages, the built-in keywords are enough. You don't need another tool for this.

If you use Jira and want commits to log time or move issues, Smart Commits are worth setting up. Check the email mapping first, since that is where most "it doesn't work" reports come from.

If your team works mostly through pull requests, branch-based linking in Linear is the smoothest of the message-based options.

The IDE-based approach makes sense when you want more than a link: a manager who can see what changed on each task without asking for a report, a board that follows your real workflow, and customers who are told when their request is finished. That is the case Vi is built for.

FAQ

Can I link a commit to a task after it has been pushed?

In message-based tools, not without rewriting the commit. Most let you add the link by hand on the task page instead. In GitHub and Linear you can also link the pull request later through its description.

Does linking commits mean the tracker reads my code?

Not necessarily. GitHub and GitLab host the code, so they already have it. Jira, Linear and Azure Boards receive commit details through an integration. Redmine reads the repository directly. Vi runs Git locally and keeps only commit details, not file contents.

What is the difference between linking and closing?

Linking attaches the commit to the task so you can see it. Closing keywords (fixes, closes, #resolve) also change the task's status. Use closing only when finishing the code really does mean the task is finished.

Can one commit be linked to several tasks?

In GitHub, GitLab, Jira and Azure Boards, yes: mention each ID in the message. In Vi each commit belongs to the task you pressed Done on, and a subtask gets its own commit.

See it in Vi

If the full chain is what you are after, From customer request to delivered code shows each step, from the first email to the customer's "done" message. For the Git side, see Git project management in Vi or watch the 40-second Commit & Close video. What is Git-aware project management? explains the idea behind it.

See it on your own repository

Install the IDE plugin, connect a project, and move a task forward from the commit that finished your part. The free plan needs no card.