Writers' Toolkit Write Tooling and workflows
Open source

Documentation tooling and workflows

Grafana manages documentation as code and stores it in version control using Git. To learn more about how to use Git, refer to Use Git.

Use Git

Although processes for contributing changes differ for each repository, at Grafana there is a generally consistent workflow.

Create a local repository

Creating a local repository is only necessary when first contributing to a GitHub repository. To create a local repository from a remote repository, use git clone with the URL of the repository.

There are two types of URL used for cloning: SSH and HTTPS. Using SSH URLs means that you don’t have to provide a username and personal access token when pushing commits. Instead, authentication with for URLs uses an SSH key. To set up SSH key authentication in GitHub, refer to Adding a new SSH key to your GitHub account.

The SSH URL for a Grafana repository is<REPOSITORY>.git. For example, the SSH URL for the Grafana Mimir repository is

Cloning a repository creates a directory containing a Git repository and a configured Git remote named origin that refers to the remote repository.

To clone the Grafana Mimir repository, for example:

git clone

The output is similar to the following:

Cloning into 'mimir'...
remote: Enumerating objects: 111551, done.
remote: Counting objects: 100% (12447/12447), done.
remote: Compressing objects: 100% (3830/3830), done.
remote: Total 111551 (delta 9389), reused 10865 (delta 8511), pack-reused 99104
Receiving objects: 100% (111551/111551), 101.82 MiB | 3.50 MiB/s, done.
Resolving deltas: 100% (73091/73091), done.

You can then enter the repository by changing to the newly created directory.

cd mimir

For a full list of Grafana repositories, refer to the GitHub repository list for the Grafana organization.

Download updated references from the remote repository

Before contributing changes to a repository, it’s important to have an up-to-date copy of the remote references so that your changes aren’t out of date. To fetch the updated references from the remote repository, use git fetch.

git fetch

If there are no updates, the command produces no output. If there are updates, the output is similar to the following:

comremote: Enumerating objects: 547, done.
remote: Counting objects: 100% (488/488), done.
remote: Compressing objects: 100% (128/128), done.
remote: Total 373 (delta 280), reused 328 (delta 242), pack-reused 0
Receiving objects: 100% (373/373), 156.38 KiB | 1.38 MiB/s, done.
Resolving deltas: 100% (280/280), completed with 79 local objects.
   659af75c3..321d1ae89  main                             -> origin/main
 * [new branch]          threaded-reader                  -> origin/threaded-reader

Create a branch from the default remote branch

By convention, the remote repository in GitHub is the source of truth for a repository’s history. The default branch of a repository is typically called main and occasionally called master. Grafana prefers to use inclusive language, so main is the preferred name.

After fetching the changes from the remote repository in GitHub, create a local branch to commit your changes. Working on your own branch separates and isolates your changes so that they can be later reviewed before incorporation into the main branch.

A branch name should be unique.

To create a branch called my-branch from the remote branch called main:

git checkout -b my-branch origin/main

The output is the following:

branch 'my-branch' set up to track 'origin/main'.
Switched to a new branch 'my-branch'

You are now on a new local branch and can begin to commit changes. This means that you are now working on a branch you’ve created to reflect the changes you’re planning to make and can use this branch to develop your content and test different layouts, approaches, or structures freely.

To check which branch you are working on, use git branch. The command outputs a list of local branches with your current branch marked with an asterisk *. For example:

git branch

The output is similar to the following:

* my-branch

Indicating that you are on the branch my-branch and there is another local branch named main.

Alternatively, you can use git status to check your current branch and understand the status of the branch.


git status relies on your local repository having the up-to-date references from the remote repository.

Run git fetch before git status for the most accurate status.

To understand the output of git status, refer to Git - git-status Documentation.

Check out a PR branch from a fork

A fork is a repository that shares code and visibility settings with the original upstream repository.

For more information, refer to About forks.

To check out a PR branch from a fork, use the GitHub CLI (gh) tool. To install the GitHub CLI tool, refer to Install GitHub CLI.

It fetches from the fork remote repository and configures a local branch in your repository to track that remote branch in the fork.

To install the GitHub CLI tool, refer to Installation.

Run the command from a directory within your local checkout of the upstream repository to check out a contributor’s PR. Replace PR NUMBER with the number of the pull request.

gh pr checkout <PR NUMBER>

The output is similar to the following:

remote: Enumerating objects: 14, done.
remote: Counting objects: 100% (9/9), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 14 (delta 7), reused 7 (delta 7), pack-reused 5
Unpacking objects: 100% (14/14), 7.68 KiB | 1.10 MiB/s, done.
 * [new ref]               refs/pull/76925/head -> patch-2
Switched to branch 'patch-2'

The GitHub CLI tool automatically configures the remote tracking branch so you can push and pull from the fork branch.


You can only push to a fork if the PR author has enabled Allow edits and access to secrets by maintainers or Allow edits by maintainers.

To enable maintainer edits, refer to Enabling repository maintainer permissions on existing pull requests.

Commit changes to your branch

Committing changes has two steps: staging and committing. You can stage whole files and directories, or you can stage individual areas within files.

Stage files and directories

To stage whole files or directories, use git add <PATH...>. To stage the file in your current working directory, for example:

git add

Stage all files relevant to your current change.

Stage individual areas within files

Diff hunks are individual areas of difference in files. Each diff hunk shows one area where a file differs between versions. You can interactively stage hunks using git add -p. git presents you with a diff hunk for each change that you have made and asks if you would like to stage it. Answering the prompt with y stages the hunk. Answering the prompt with n skips staging the hunk. Answering the prompt with q skips staging the hunk and any remaining hunks. Answering the prompt with a stages the hunk and any remaining hunks.

Using the prompt, stage all hunks relevant to your current change.

After you have staged your changes, you can commit them with git commit -s. git opens your text editor where you can type a commit message.


The -s flag adds a Signed-off-by message to your commits that states you agree to the terms published at for that particular commit.

This is a requirement for a number of repositories.

The first line of a message is the subject. Commit subjects should be descriptive and concise and are typically written in the imperative, present tense. To provide additional information, leave a blank line after the subject and write a commit body. For example:

Use American English spellings

American English is preferred by our technical documentation style-guide.
For more information, refer to

Save and close the file opened by git to finish the commit.

For small changes where you only need write a subject, use the -m flag to provide the message without invoking your editor. For example:

git commit -s -m "Use American English spellings"

Push changes to the remote repository

Pushing changes to the remote repository allows other people to look at your commits and review them. It’s also the first step in getting your changes incorporated into the main branch.

Push your changes using git push.

To push your local branch called my-branch to a remote branch of the same name:

git push -u origin my-branch

The output is similar to the following:

Enumerating objects: 14, done.
Counting objects: 100% (14/14), done.
Delta compression using up to 8 threads
Compressing objects: 100% (8/8), done.
Writing objects: 100% (10/10), 3.34 KiB | 3.34 MiB/s, done.
Total 10 (delta 5), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (5/5), completed with 3 local objects.
remote: Create a pull request for 'my-branch' on GitHub by visiting:
 * [new branch]      HEAD -> my-branch
branch 'my-branch' set up to track 'origin/my-branch'.

The response from GitHub includes a link used to open a pull request for your remote branch. Click the link to open GitHub, then click the green button on the upper left of the screen to open the pull request for reviewers. Here, you can also edit the title and further detail in the larger text box as well as add reviewers by clicking the Settings icon and entering reviewer GitHub usernames.

Force push changes

If you rewrite local history, or your local branch diverges from the one in the remote for other reasons, you might need to force the remote to accept your changes.

In such cases, prefer --force-with-lease over --force, which overwrites the branch in the remote only if you have a tracking branch that’s up to date. That way, you won’t accidentally overwrite commits pushed by others that you didn’t know about. For more information, refer to the documentation of the option in man git-push.

Merge changes from the main branch

Because Git and GitHub are naturally collaborative, others are also making and merging pull requests at the same time as you. From the point where you created your branch and when you’re ready to merge the pull request, the main branch might have changed in significant ways, or even developed a conflict with your branch.

If the changes don’t conflict, you can use Git to incorporate the changes made to the main branch with yours without making any additional changes.

First, fetch changes to all branches and remotes:

git fetch --all

Update your local copy of the main branch by merging the remote changes into it:

git switch main
git merge --ff-only

After switching branches, Git also lets you know if your local copy needs updating with the message Your branch is behind ‘origin/main’. The --ff-only flag means fast-forwarding, which simply applies the changes to the end of your local copy because your local copy has no conflicting changes.

Switched to branch 'main'
Your branch is behind 'origin/main' by 30 commits, and can be fast-forwarded.
  (use "git pull" to update your local branch)

Now switch back to your branch and merge the main branch into it, applying its changes into yours:

git switch my-branch
git merge main

If there are no changes to apply, Git confirms this:

$ git merge main

The output is similar to the following:

Already up to date.

Otherwise, if successful, Git outputs the changes it applied to your branch:

$ git merge main

The output is similar to the following:

Removing public/app/plugins/panel/geomap/utils/view.ts
Auto-merging .github/CODEOWNERS
Merge made by the 'recursive' strategy.
 .betterer.results                                                           |  142 +--
 .drone.yml                                                                  |  351 ++++++-
 .github/CODEOWNERS                                                          |    3 +

Resolve conflicts

GitHub and Git both warn you when the source branch and your branch directly conflict.

GitHub notifies you in the pull request if your branch conflicts with the target branch. If the conflict is easy to resolve, GitHub offers to help you resolve it using the web editor. For more information refer to About merge conflicts.

If the conflict is too complex to resolve in the web editor, GitHub directs you to resolve it on the command line.

If there’s a conflict when attempting to merge the target branch branch into yours, Git also tells you which files are in conflict:

$ git merge main
Auto-merging .github/CODEOWNERS
CONFLICT (content): Merge conflict in .github/CODEOWNERS
Automatic merge failed; fix conflicts and then commit the result.

GitHub has detailed, cross-platform instructions for resolving a merge conflict using Git on the command line. For more information refer to Resolving a merge conflict using the command line.

Use GitHub CLI

GitHub CLI simplifies some Git workflows when working with GitHub repositories.

Install GitHub CLI

To install the GitHub CLI tool, refer to Installation.