GitHub contribution workflow for major or long-running changes
All repositories that publish to docs.microsoft.com have adopted the Microsoft Open Source Code of Conduct. For more information, see the Code of Conduct FAQ. Or contact firstname.lastname@example.org with any questions or comments.
This workflow is suitable for a contributor who needs to make a major change or will be a frequent contributor to a repository. Frequent contributors typically have ongoing (long-running) changes, which go through multiple build/validation/staging cycles or span multiple days before pull request sign-off and merge.
For Microsoft employees who are working on projects that use both public and private repositories, it's also important to make these types of contributions to the private repository. Integrated OPS build, validation, and staging services are available in the private repository.
Examples of these types of contributions include:
- Making a large contribution. For instance, you might make contributions (additions, changes, or deletions) that span multiple articles and need to be committed and tested as one unit of work in a single pull request.
- Creating and publishing a new article, which typically requires a more robust local editor. If you are a Microsoft employee, you might need to use the VS Code extensions discussed in Install Git/Markdown tools, for example.
- Adding new images or updating images, which typically requires simultaneous creation of a new
mediasubdirectory, image files, updates to image links in articles, and previewing markdown files in a local editor to test image rendering.
- Updating an article over a period of days before you publish. In these cases, you typically need to do regular integration of other changes that occur in the master branch. This integration is easier via Git Bash and local editing. You also run the risk of losing your edits if you do this via the GitHub UI and wait before you commit the changes.
- Making continual updates to the same article after a pull request has been opened (unless you are comfortable doing this via the GitHub UI). Using the GitHub UI has the potential to create multiple outstanding pull requests for the same file, which may conflict with one another.
Before you start, let's review some of the Git/GitHub terms and monikers used in this workflow. Don't worry about understanding them now. Just know that you will be learning about them, and you can refer back to this section when you need to verify a definition.
|fork||Normally used as a noun, when referring to a copy of a main GitHub repository. In practice, a fork is just another repository. But it's special in the sense that GitHub maintains a connection back to the main/parent repository. It's sometimes used as a verb, as in "You must fork the repository first."|
|remote||A named connection to a remote repository, such as the "origin" or "upstream" remote. Git refers to these as remotes because they are used to reference a repository that's hosted on another computer. In this workflow, a remote is always a GitHub repository.|
|origin||The name assigned to the connection between your local repository and the repository from which it was cloned. In this workflow, origin represents the connection to your fork. It's sometimes used as a moniker for the origin repository itself, as in "Remember to push your changes to origin."|
|upstream||Like the origin remote, upstream is a named connection to another repository. In this workflow, upstream represents the connection between your local repository and the main repository, from which your fork was created. It's sometimes used as a moniker for the upstream repository itself, as in "Remember to pull the changes from upstream."|
If you haven't already, you must complete the steps in the Setup section. This section walks you through setting up your GitHub account, installing Git Bash and a Markdown editor, creating a fork, and setting up your local repository. If you are unfamiliar with Git and GitHub concepts such as a repository or branch, please first review Git and GitHub fundamentals.
In this workflow, changes flow in a repetitive cycle. Starting from your device's local repository, they flow back up to your GitHub fork, into the main GitHub repository, and back down locally again as you incorporate changes from other contributors.
1. Create a working branch
Recall from Git and GitHub fundamentals that a Git repository contains a master branch, plus any additional work-in-progress branches that have not been integrated into master. Whenever you introduce a set of logically related changes, it’s a best practice to create a working branch to manage your changes through the workflow. We refer to it here as a working branch because it's a workspace to iterate/refine changes, until they can be integrated back into the master branch.
Isolating related changes to a specific branch allows you to control and introduce those changes independently, targeting them to a specific release time in the publishing cycle. In reality, depending on the type of work you do, you can easily end up with several working branches in your repository. It's not uncommon to be working on multiple branches at the same time, each representing a different project.
Making your changes in the master branch is not a good practice. Imagine that you use the master branch to introduce a set of changes for a timed feature release. You finish the changes and are waiting to release them. Then in the interim, you have an urgent request to fix something, so you make the change to a file in the master branch and then publish the change. In this example, you inadvertently publish both the fix and the changes that you were holding for release on a specific date.
Now let's create a new working branch in your local repository, to capture your proposed changes:
Start Git Bash.
Switch the context to your local repository, by using the Git Bash
cd <repo>(change directory) command. Recall that your new local repository was created by the clone command, in a subdirectory under the path
Let's pause at this point, and review some fundamental concepts that will be important as you learn how to use Git:
a. Working directory: The previous
cdcommand caused the Git Bash context to be changed to the repository directory that the clone command created. This repository is used for two purposes:
- To provide a working directory, where you can make additions, changes, and deletions to a branch's files by using your Markdown editor and other programs. The files belong to the current branch.
- To store the local repository. This is essentially a database where Git manages repository data structures, including the state of all of its branches, the remote "origin" and "upstream" connections, and other internal details. You use Git commands to transfer your files to/from the working directory and the Git repo database, instead of working directly in the repo database.
b. Current branch: The Git Bash context was also set to the branch in the local repo where your changes will be applied, referred to as the current branch. Git Bash defaults to the default/master branch for a newly cloned repo, or the last branch that you worked on in an existing repo.
Working directory is an operating system concept, whereas current branch is a Git concept. Think of the current branch as just an alias for the branch that you are working on, not a new or different branch. Because you can't operate directly on a branch in Git's local repository (that is, the database), the working directory provides a place to add, edit, and delete the current branch's files before you save them back to the local repository. This will become clearer later in the next section, and as you get accustomed to working in Git.
c. Git Bash environment: Before you make any changes to files, it's always a good idea to verify the context of your current Git Bash environment. This context includes the repository and branch that the Git commands will operate on. This is especially important if you have switched to work on other repositories or branches (or possibly a different computer) since the time of creation, or last use, of the repository. In the following Git Bash screenshot, you'll notice that the first line in the command prompt contains the following:
- The user account that you used to sign in to your computer, and the network name of your computer (
- The location of the current repository's working directory (
/c/Git/Azure-Docsin yellow, which maps to
c:\Git\Azure-Docson a Windows computer)
The current branch being worked on (
The previous screenshot also shows the use of the
git branchcommand, which is used to list the available branches in the local repository. This is useful if you need to verify the current branch (prefixed with an asterisk), or you need to get the list of available branches before switching to a new one.
checkoutcommand to select the branch you want to designate as the current branch:
git checkout master
checkoutcommand does the following:
- Pulls the master branch files out of the local repository
- Copies the files into the working directory for editing
- Selects the master branch as the new current branch (which you can verify in the Git command prompt)
Create a new working branch in your local repository.
a. If you are not collaborating on a project with others, you can skip this step. If you are collaborating, you will likely need to base the creation of your working branch on an upstream release branch. So before you create your working branch, you'll need to make your local repository aware of new release branches in your upstream repository by using the following command:
git fetch upstream
b. To create your working branch, you again use the
checkoutcommand, but this time with additional arguments. Run the following command, by substituting the name that you want to use for your new branch in place of
masterif you are working independently of others, or the name of a release branch if you are collaborating with others on release work. The
-bswitch will cause Git to first create a local working branch, based on the remote
upstream/<parent-upstream-branch>branch, and then select it as your new current branch.
git checkout -b <my-working-branch> upstream/<parent-upstream-branch>
If you receive an error from the
checkoutcommand in 5.b., make sure that you completed the
fetch upstreamcommand in 5.a. first. Also, make sure that you completed all steps in the "Setup" section of this guide, including Local repository setup. This will ensure that your "upstream" connection to the main repository is established correctly.
Establish a copy of your new branch in your fork for future synchronization. The following
git pushcommand will push/upload a copy of your new
<my-working-branch>to your fork/origin repository. Be sure to replace
<my-working-branch>with the same working branch name that you specified in step 5. You use the
-uswitch here and only once in this workflow, which saves additional remote branch tracking information for use by Git:
git push -u origin <my-working-branch>
This section was devoted to work that is usually done only once, at the beginning of the workflow for each contribution project. Each time you start a new project, you will want to review the steps in this section.
Let's summarize what you've completed so far:
- Learned about the Git Bash environment and context, important local repository concepts such as the working directory and current branch, and how Git uses them to manage work in your local repository
- Learned how to select a new branch into the working directory, designating it as the current branch
- Created a new working branch in your local repository, based on a branch from your main/upstream repo, and selected it into the working directory as the new current branch
- Pushed a copy of the new working branch up to your fork/origin repo, for future synchronization and use in creating a pull request
In the next section, you will learn about the recurring steps in the workflow. You typically do these multiple times as you iterate and perfect your contributions.
2. Make changes to your current branch
Another important concept to understand is a commit. Git tracks the set of changes you make, in a unit of work called a commit. A commit is a group of related changes, additions, and deletions applied to one or more of the current branch's files, at a point in time. Commits enable Git to operate on a finite boundary of work, and they give you an easy way to reference the changes later if necessary.
Because updates from other contributors happen frequently and simultaneously during the life of your working branch, it's a good practice to first ensure that their changes are integrated into your branch. This will also help you either prevent merge conflicts, which occur when changes from others cannot be reconciled with your branch, or discover them before they get more complex.
In the following command, replace
<parent-branch-name>with the name of the remote branch from which your working branch was created in step 5 of the previous section (for example,
release-0918). Note that this command assumes that you still have the desired working branch selected as your current branch.
git pull upstream <parent-branch-name>
This command downloads the latest changes from the specified upstream branch and merges them into the current branch. If Git can't merge them due to a merge conflict, see Resolve merge conflicts in Git and GitHub for details on how to resolve it. It's a good practice to get into the habit of doing this regularly throughout each day, to proactively reduce or prevent merge conflicts.
Make your file changes. You typically use File Explorer and/or your Markdown editor to create, modify, or delete Markdown files from within your repository's working directory. If you need assistance with Markdown syntax, see How to use Markdown.
As you create, modify, or delete files in your working directory, two things are happening:
- The operating system is persisting the changes in your working directory to disk, just as it would any file changes.
- Git is monitoring the working directory for changes. As you recall, the working directory is where the current branch is being modified. Git does this in order to capture your activity, waiting for you to specify when the pending work should be committed to the local repository.
So even though the working directory changes are persisted to your file system, they are not yet persisted to the local repository's copy of the working branch. After the changes in your working directory are committed, the state of your working directory and the current branch as it exists in the local repository will be the same.
You can verify the state of Git's change tracking in the working directory, by using the Git
In the following example, you can see in red that the working directory has had two tracked changes (one modified and one deleted file) and an untracked change (a new file). None of them have been committed and persisted to the current branch in the local repository.
You are likely beginning to notice that persisting changes to your local repo is a multistep process. After the changes are saved in the working directory (file system), there are two additional steps that tell Git to:
- Add the tracked and untracked changes in the working directory to Git's staging area (also known as the index). You can think of the staging area as a holding area that's used to queue the changes that you want to bundle together under the same commit operation.
- Commit everything in the staging area, to the local repository's persistent copy of the working branch.
You do this by using following pair of commands, respectively. Be sure to use a capital A in the
-Aswitch, and replace
<comment>with a comment to capture a short description of your change.
git add -A git commit –m "<comment>"
After you complete the two-step commit process, the state of the current branch in the local repository will match the state of your working directory. You will find yourself repeating the add/commit steps several times as you add, change, or delete files in your working directory.
If you want to learn more about this process, including details of the staging/committing process, see the Git Basics - Recording Changes to the Repository topic in the Pro Git e-book.
Finally, use the
git pushcommand again (but without the
-uswitch), to synchronize your local repo's current branch with the branch of the same name that you uploaded/pushed to your GitHub fork in the previous section:
git push origin <my-working-branch>
You should also do this on a regular basis, to ensure that your changes are backed up on GitHub. If you've already opened a pull request (discussed in a later section), each time you push your branch the pull request will sense the new commits and rerun any automated build/validation steps that are required.
If all your Git Bash commands finished successfully, you should see responses to each, similar to the following screenshot. Notice that the
commit command successfully committed the three file changes to the local repository, and the
push command successfully pushed the current branch up to the fork.
This section was devoted to steps of the workflow that tend to be recurring, which you will use several times throughout the life of a working branch. Next we will review the last part of the workflow, which you will do when you believe your contribution is ready to be proposed back into the master branch.
3. Open a pull request
When you are ready to submit your content for validation and publishing:
Go to your fork's GitHub page, for example,
Next you will create the pull request. A pull request is a proposal to pull the commits on your working branch, into the parent branch in the main repo from which you created your working branch (in step 5 of the Create a working branch section).
Select the working branch you pushed to your fork (in step 5 of the Make changes to your current branch section), by using the Branch: button on the left. Then select the New pull request button to the right to initiate a new pull request:
When the Open a pull request page appears, verify that your "head" fork and working branch are shown on the right (from), and the docs.microsoft.com "base" repo and parent branch are on the left (to):
The PR title defaults to a comment that matches the one used in your commit, but you should make sure that it's descriptive. You can also do a quick scan to see if the number of files that you modified matches the number shown on the bottom of the page. If you scroll down, you can also review the exact differences between the branches, so you can verify that the pull request contains the changes/commits that you expect. If the pull request looks correct, select the Create pull request button near the bottom.
Pull request processing
The previous section walked you through the process of submitting proposed changes, by bundling them in a new pull request (PR) that is added to the destination repository's PR queue. A pull request enables GitHub's collaboration model, by asking for the changes from your working branch to be pulled and merged into another branch. In most cases, that other branch is the default/master branch in the main repository.
Before your pull request can be merged into its destination branch, it might be required to pass through one or more PR validation processes. Validation processes can vary depending on the scope of proposed changes and the rules of the destination repository. After your pull request is submitted, you can expect one or more of the following to happen:
- Mergeability: A baseline GitHub mergeability test occurs first, to verify whether the proposed changes in your branch are in conflict with the destination branch. If the pull request indicates that this test failed, you must reconcile the content that is causing the merge conflict before processing can continue.
- CLA: If you are contributing to a public repository and are not a Microsoft employee, depending on the magnitude of the proposed changes, you might be asked to complete a short Contribution License Agreement (CLA) the first time you submit a pull request to that repository. After the CLA step is cleared, your pull request is processed.
- Labeling: Labels are automatically applied to your pull request, to indicate the state of your pull request as it passes through the validation workflow. For instance, new pull requests might automatically receive the "do-not-merge" label, indicating that the pull request has not yet completed the validation, review, and sign-off steps.
- Validation and build: Automated checks verify whether your changes pass validation tests. The validation tests might yield warnings or errors, requiring you to make changes to one or more files in your pull request before it can be merged. The validation test results are added as a comment in your pull request for your review, and they might be sent to you in e-mail.
- Staging: The article pages affected by your changes are automatically deployed to a staging environment for review upon successful validation and build. Preview URLs appear in a PR comment.
- Auto-merge: The pull request might be automatically merged, if it passes validation testing and certain criteria. In this case, you don't need to take any further action.
Review and sign-off
After all PR processing is completed, you should review the results (PR comments, preview URLs, etc.) to determine if additional changes to its files are required before you sign off for merging. If a PR reviewer has reviewed your pull request, they can also provide feedback via comments if there are outstanding issues/questions to be resolved prior to merge.
Comment automation enables read-level users (users who don't have write permissions in a repo) to perform a write-level action, by assigning the appropriate label to a pull request. If you are working in a repository where comment automation has been implemented, use the hashtag comments listed in the following table to assign labels, change labels, or close a pull request. Microsoft employees will also be notified via e-mail for review and sign-off of public repository PRs, whenever changes are proposed to articles for which you are the author.
|Hashtag comment||What it does||Repo availability|
|#sign-off||When the author of an article types the #sign-off comment in the comment stream, the ready-to-merge label is assigned. This label lets the reviewers in the repo know when a pull request is ready for review/merge.||Public and private|
|#sign-off||If a contributor who is not the listed author tries to sign off on a public pull request by using the #sign-off comment, a message is written to the pull request indicating that only the author can assign the label.||Public|
|#hold-off||Authors can type #hold-off in a PR comment to remove the ready-to-merge label--in case they change their mind or make a mistake. In the private repo, this assigns the do-not-merge label.||Public and private|
|#please-close||Authors can type #please-close in the comment stream to close the pull request if they decide not to have the changes merged.||Public|
When the pull request is issue-free and signed off, your changes are merged back into the parent branch and the pull request is closed.
Remember, your pull request has to be merged by a PR reviewer before the changes can be included in the next scheduled publishing run. Pull requests are normally reviewed/merged in the order of submission. If your pull request requires merging for a specific publishing run, you will need to work with your PR reviewer ahead of time to ensure that merging happens prior to publishing.
After your contributions are approved and merged, the docs.microsoft.com publishing process picks them up. Depending on the team that manages the repository you are contributing to, publishing times can vary. Articles published under the following paths are normally deployed at approximately 10:30 AM and 3:30 PM Pacific Time, Monday-Friday:
It can take up to 45 minutes for articles to appear online after publishing. After your article is published, you can verify your changes at the appropriate URL:
That's it! You've made a contribution to docs.microsoft.com content!
For additional information on the pull request process, see Pull request best practices.
To learn more about topics such as Markdown and Markdown extensions syntax, continue to the "Writing essentials" section.