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 that needs to make a major change, or will be a frequent contributor to a repository. Frequent contributors typically have ongoing or "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 working on projects that utilize both public and private repositories, it's also important to make these types of contributions to the private repository, where integrated OPS build/validation/staging services are available.
Examples of these types of contributions include:
- Making a large contribution. For instance, contributions (additions/changes/deletions) that span multiple articles and need to be committed/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 may 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 occurring in the 'master' branch, which 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, waiting 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 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 being 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 will walk 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/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 to "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 as it's a work space 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 could easily end up with several working branches in your repository. It's not uncommon to be working on multiple at the same time, each representing a different project.
Making your changes in the 'master' branch is not a good practice. Imagine if you used the 'master' branch to introduce a set of changes for a timed feature release. You finished the changes, and were waiting to release them. Then in the interim, you had an urgent request to fix something, so you made the change to a file in the 'master' branch then published the change. In this example, you would have inadvertently published both the fix and the changes to 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:
Launch Git Bash.
Switch context to your local repository, by using the Git Bash
cd <repository-name>(change directory) command. Recall that your new local repository was created by the clone command, in a subdirectory under the path
Lets 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, which is actually used for two purposes:
- To provide a working directory, where you can make additions/changes/deletions to a branch's files using your Markdown editor and other programs. Specifically, files belonging to the current branch as defined below.
- 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 will default to the default/"master" branch for a newly cloned repo, or the last branch you worked on in an existing repo.
Working directory is an operating system concept, whereas current branch is a Git concept. Think of current branch as just an alias for the branch you are working on, NOT a new/different branch. Because you can't operate directly on a branch in Git's local repository (ie: the database), the working directory provides a place to add/edit/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 making any changes to files, it's always a good idea to verify the context of your current Git Bash environment, including the repository and branch 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 Git Bash screenshot below, you'll notice that the top "command prompt" line contains the following:
- The user account you used to log into your computer, and the network name of your computer (
useracct@computerin green )
- 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 (
masterin blue ).
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 get the list of available branches before switching to a new one.
Next, you will use the
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)
Now you will 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 collaborting, 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 will again use the
checkoutcommand, but this time with additional arguments. Run the following command, by substituting the name you'd like to use for your new branch in place of
<parent-upstream-branch>, substitute "master" if 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 upon the remote
upstream/<parent-upstream-branch>branch, then select it as your new current branch:
git checkout -b <my-working-branch> upstream/<parent-upstream-branch>
If you received an error from the
checkoutcommand, make sure you complete the steps in the Setup section first, including Setup your local repository. This will ensure your "upstream" connection to the main repository is established correctly.
Finally, you need to establish a copy of your new branch in your fork for future synchronization. The
git pushcommand below 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 you specified in step #5. You will use the -u switch 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 upon a branch from your main/upstream repo, selecting 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, which are typically done 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/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 give you an easy way to reference later if necessary.
Since updates from other contributors happen frequently and simultaneous during the life of your working branch, it's a good practice to first ensure 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 earlier before they get more complex.
In the command below, insert the name of the remote branch from which your working branch was created in the step #5 of the previous section (ie: "master", "release-0918", etc.), in place of
<parent-branch-name>. 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 will download the latest changes from the specified upstream branch, and merge them into the current branch. If Git is unable to merge them due to a merge conflict, see Git tips and troubleshooting for details on how to resolve. It's a good practice to get into the habit of doing this regularly throughout each day, to proactively reduce/prevent merge conflicts.
Now you can go ahead and make your file changes. You'll typically use Windows Explorer and/or your Markdown editor to create/modify/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/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, which, as you recall, 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 branch in the local repository being represented by the current branch. Once the changes in your working directory have been 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 2 "tracked changes" (1 modified, 1 deleted file) and 1 "untracked change" (a new file), none of which 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 multi-step process. After they are saved in the working directory (file system), there are two additional steps which tell Git to:
- First "add" the tracked and untracked changes in the working directory, to Git's "staging area" (aka: Index). You can think of the staging area as a holding area, used to queue up the changes you want to bundle together under the same commit operation.
- Then "commit" everything in the staging area, to the branch in the local repo being represented by the current branch.
This is done by using following pair of commands respectively. Be sure to use a capital A in the
-Aswitch, and enter a
<comment>to capture a short description of your change :
git add -A git commit –m "<comment>"
Once you complete the 2-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/delete files in your working directory.
If you'd like to learn more about this entire process, including graphic details of the staging/committing process, see the Git Basics - Recording Changes to the Repository topic in the Pro Git e-book.
Finally, you'll use the
git pushcommand again (but without the -u switch), 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 your changes are backed up on GitHub. If you've already opened a pull request (discussed in the next section), each time you push your branch the pull request will sense the new commits and rerun any automated build/validation steps required.
If all of your Git Bash commands completed successfully, you should see responses to each, similar to the following. Notice that the
commit command successfully committed the 3 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), using the Branch: button on the left. Then click the New pull request button to the right to initiate a new Pull Request:
When the "Open a pull request" page displays, 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 will be defaulted to a comment that matches the one used in your commit, but you should review and make sure it's descriptive. You can also do a quick scan to see if the number of files 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, allowing you to verify that the pull request contains the changes/commits you expect. If the Pull Request looks correct, click 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) which is added to the destination repository's pull request 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, into the default/"master" branch in the main repository.
Before your PR can be merged into its destination branch though, it may be required to pass through one or more PR validation processes, which can vary depending on the scope of proposed changes and the rules of the destination repository. After your pull request has been submitted, you can expect one or more of the following to happen:
- Mergeability: A baseline GitHub mergeability test will occur first, to verify whether the proposed changes in your branch are in conflict with the destination branch. If the PR indicates that this test failed, you must reconcile the content that is causing the merge conflict(s) 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 may be asked to complete a short Contribution License Agreement (CLA) the first time you submit a PR to that repository. Once the CLA step has cleared, your PR will be processed.
- Labeling: Labels may be automatically applied to your PR, which are used to indicate the state of your PR as it passes through the validation workflow. For instance, new PRs may automatically receive the "do-not-merge" label, indicating that the PR is has not yet completed the validation, review, and sign-off steps.
- Validation/Build: Your changes may be examined by a series of automated checks to verify whether they pass validation testing. The validation tests may yield warnings/errors, requiring you to make changes to one or more files in your PR before it can be merged. The validation test results will be added as a comment in your PR for your review, and may also be sent to you via e-mail.
- Staging: The article pages impacted by your changes may automatically be deployed to a staging environment for review upon successful validation and build, with "Preview URLs" made available in a PR comment.
- Auto-Merge: The PR may be automatically merged, if it passes validation testing and certain criteria. In this case, there is no further action required by you.
Review and sign-off
Once all PR processing has 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 your PR has been reviewed by a PR reviewer, they may also provide feedback via comments if there are outstanding issues/questions to be resolved prior to merge.
Comment automation enables read-level users (users that 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 comment listed in the following table to assign labels to let the reviewers in your repo know when a PR is ready for review/merge, to change the label status of a PR, or to close a PR. 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.||Public and private|
|#sign-off||If a contributor who is NOT the listed author tries to sign off on a public pull request using the #sign-off comment, a message is written to the pull request indicating the label can be assigned only by the author.||Public|
|#hold-off||If you type #hold-off in a pull request comment, it removes the ready-to-merge label - in case you change your mind or make a mistake. In the private repo, this assigns the do-not-merge label.||Public and private|
|#please-close||Authors can type the #please-close comment in the comment stream of a pull request to close it if you decide not to have the changes merged.||Public|
Once the pull request is issue-free and signed-off, your changes will be merged back into the parent branch and the PR will be closed.
Remember, your pull request has to be merged by a pull request reviewer before the changes can be included in the next scheduled publishing run. PRs are normally reviewed/merged in the order they were submitted. If your pull request requires merging for a specific publishing run, you will need to work with your pull request reviewer ahead of time to ensure merge happens prior to publishing.
Once your contributions have been approved and merged, they will be picked up by the Docs.Microsoft.Com publishing process. 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. Once your article has been published, you can verify your changes at the appropriate URL:
That's it! You've made a contribution to Docs.Microsoft.Com content!
See Pull request best practices for additional information on the pull request process.
Continue to the Writing essentials section to learn more about topics such as Markdown and Markdown extensions syntax, and more.