|  | --- | 
|  | title: GitHub Notes | 
|  | --- | 
|  |  | 
|  | The OpenTitan source tree is maintained on GitHub in a [monolithic repository](https://github.com/lowRISC/opentitan) called opentitan. | 
|  |  | 
|  | These notes are for people who intend to contribute back to OpenTitan (based on | 
|  | notes taken by a relatively inexperienced git user). If you don't intend to do | 
|  | this you can simply clone the main repository, instructions are in [install | 
|  | instructions]({{< relref "doc/getting_started" >}}) and this document can be | 
|  | ignored.There is much more to using git, a possible next step is to reference | 
|  | [Resources to learn Git](https://try.github.io/). | 
|  |  | 
|  | ## Getting a working repository | 
|  |  | 
|  | To develop in the repository you will need to get a copy on your local | 
|  | machine. To allow contributions to be made back to the main repo | 
|  | (through a process called a Pull Request) you need to first make your | 
|  | own copy of the repository on GitHub then transfer that to your local | 
|  | machine. | 
|  |  | 
|  | You will need to log in to GitHub, go to the [opentitan repository](https://github.com/lowRISC/opentitan) and click on | 
|  | "Fork". This will generate a copy in your GitHub area that you can | 
|  | use. | 
|  |  | 
|  | Then setup git on your local machine and set some standard parameters | 
|  | to ensure your name and email are correctly inserted. These commands | 
|  | set them globally for all your use of git on the local machine so you | 
|  | may have done this step already, there is no need to repeat it. (See | 
|  | below if you want to use a different email address for this repo.) | 
|  |  | 
|  | Check the parameters: | 
|  | ```console | 
|  | $ git config -l | 
|  | ``` | 
|  |  | 
|  | And if they do not exist then set them: | 
|  |  | 
|  | ```console | 
|  | $ git config --global user.name "My Name" | 
|  | $ git config --global user.email "my_name@email.com" | 
|  | ``` | 
|  |  | 
|  | `git` will take care of prompting for your GitHub user name and | 
|  | password when it is required, but it can be useful to allow it to | 
|  | cache these credentials (set here to an hour using the timeout in | 
|  | seconds) so you don't have to enter every time: | 
|  |  | 
|  | ```console | 
|  | $ git config --global credential.helper 'cache --timeout=3600' | 
|  | ``` | 
|  |  | 
|  | Now make a local copy of your GitHub copy of the repository and let git know | 
|  | that it is derived from the **upstream** lowRISC repo: | 
|  |  | 
|  | ```console | 
|  | $ cd <where the repository should go> | 
|  | $ git clone https://github.com/$GITHUB_USER/opentitan.git | 
|  | $ cd opentitan | 
|  | $ git remote add upstream https://github.com/lowRISC/opentitan.git | 
|  | $ git fetch upstream | 
|  | $ git remote -v | 
|  | ``` | 
|  |  | 
|  | The `git remote -v` should give your GitHub copy as **origin** and the | 
|  | lowRISC one as **upstream**. Making this link will allow you to keep your | 
|  | local and GitHub repos up to date with the lowRISC one. | 
|  |  | 
|  | If you want a different email address (or name) for the lowRISC repository then | 
|  | you can set it locally in the repository (similar to above but without the | 
|  | --global flag). This command must be executed from a directory inside | 
|  | the local copy of the repo. (There is no need for the first `cd` if | 
|  | you are following the previous step.) | 
|  |  | 
|  |  | 
|  | ```console | 
|  | $ cd opentitan | 
|  | $ git config user.email "my_name@lowrisc.org" | 
|  | ``` | 
|  |  | 
|  | ## Working in your local repo | 
|  |  | 
|  | The repository that you have created locally will initially be on the | 
|  | `master` branch. In general you should not make changes on this | 
|  | branch, just use it to track your GitHub repository and synchronize with the | 
|  | main lowRISC repository. | 
|  |  | 
|  | The typical workflow is to make your own branch which it is | 
|  | conventional to name based on the change you are making: | 
|  |  | 
|  | ```console | 
|  | $ git checkout -b forchange | 
|  | $ git status | 
|  | ``` | 
|  |  | 
|  | The status will initially indicate there are no changes, but as you | 
|  | add, delete or edit files it will let you know the state of things. | 
|  |  | 
|  | Once you are happy with your changes, commit them to the local repository by adding the files to the changes (if things are clean you can add using `git commit -a -s` instead of a number of `add` commands): | 
|  |  | 
|  | ```console | 
|  | $ git add... | 
|  | $ git commit -s | 
|  | ``` | 
|  |  | 
|  | The commit will make you add a message. The first line of this is a | 
|  | short summary of the change. It should be prefixed with a word in | 
|  | square brackets indicating the area being changed, typically the IP or | 
|  | Tool name. For example: | 
|  |  | 
|  | ```console | 
|  | [doc/um] Add notes on using GitHub and the repo | 
|  | ``` | 
|  |  | 
|  | After this there should be a blank line and the main description of | 
|  | the change. If you are fixing an issue then add a line at the end of | 
|  | the message `Fixes #nn` where `nn` is the issue number. This will link | 
|  | the fix and close out the issue when it is added to the lowRISC repo. | 
|  | If the change is an attempted fix that has not yet had confirmation from | 
|  | verification engineers, it should not close the related issue. In this case, | 
|  | write `Related to #nn` in the commit message rather than `Fixes #nn`. | 
|  |  | 
|  | The commit message will end with a "Signed-off-by" line inserted by `git` due to using the `-s` option to `git commit`. | 
|  | Adding this line certifies you agree to the statement in [CONTRIBUTING.md](https://github.com/lowRISC/opentitan/blob/master/CONTRIBUTING.md), indicating your contribution is made under our Contributor License Agreement. | 
|  |  | 
|  | When you have finished everything locally (it is good practice to do a | 
|  | status check to ensure things are clean) you can push your branch (eg | 
|  | forchange) to **your** GitHub repository (the **origin**): | 
|  |  | 
|  | ```console | 
|  | $ git status | 
|  | $ git push origin forchange | 
|  | ``` | 
|  |  | 
|  | Then you need to go to your repository in GitHub and either select branch | 
|  | from the pulldown or often there is a status message that you can | 
|  | click on, review the changes and make a Pull Request. You can add | 
|  | reviewers and get your change reviewed. | 
|  |  | 
|  | If you need to make changes to satisfy the reviews then you do that in | 
|  | your local repository on the same branch. You will need to `add` files and | 
|  | commit again. It is normally best to squash your changes into a single | 
|  | commit by doing it with `--amend` which will give you a chance to edit | 
|  | the message. If you do this you need to force `-f` the push back to | 
|  | your repo. | 
|  |  | 
|  | ```console | 
|  | $ git add... | 
|  | $ git commit --amend | 
|  | $ git status | 
|  | $ git push -f origin forchange | 
|  | ``` | 
|  |  | 
|  | Once the reviewers are happy you can "Rebase and Merge" the Pull | 
|  | Request on GitHub, delete the branch there (it offers to do this when | 
|  | you do the merge). You can delete the branch in your local repository with: | 
|  |  | 
|  | ```console | 
|  | $ git checkout master | 
|  | $ git branch -D forchange | 
|  | ``` | 
|  |  | 
|  | When a Pull Request contain multiple commits, those commits should be logically | 
|  | independent. Interactive rebase can be used to manipulate commits in a pull | 
|  | request to achieve that goal. Commonly, it might be used to squash commits that | 
|  | fix up issues reported during review back into the relevant commit. | 
|  |  | 
|  | ```console | 
|  | $ git rebase -i `git merge-base {current_branch} master` | 
|  | ``` | 
|  |  | 
|  | Then, an editor will open. Follow the instructions given there, to reorder and | 
|  | combine commits, or to change the commit message. Then update the PR branch in | 
|  | the GitHub remote repository. | 
|  |  | 
|  | ```console | 
|  | $ git push -f origin HEAD | 
|  | ``` | 
|  |  | 
|  | ## Automatically adding a Signed-off-by line for your commits | 
|  |  | 
|  | One option to avoid having to remember to add `-s` to `git commit` is to configure `git` to append it to your commit messages for you. | 
|  | This can be done using an executable hook. | 
|  | An appropriate hook can be installed by executing this from the root of your repository checkout: | 
|  |  | 
|  | ```console | 
|  | $ cat <<"EOF" > .git/hooks/prepare-commit-msg | 
|  | #!/bin/sh | 
|  |  | 
|  | # Add a Signed-off-by line to the commit message if not already present. | 
|  | git interpret-trailers --if-exists doNothing --trailer \ | 
|  | "Signed-off-by: $(git config user.name) <$(git config user.email)>" \ | 
|  | --in-place "$1" | 
|  | EOF | 
|  | $ chmod +x .git/hooks/prepare-commit-msg | 
|  | ``` | 
|  |  | 
|  | ## Update your repository with changes in the lowRISC repo | 
|  |  | 
|  | There is a little work to do to keep everything in sync. Normally you | 
|  | want to first get your local repository `master` branch up to date with the | 
|  | lowRISC repository (**upstream**) and then you use that to update your GitHub | 
|  | copy (**origin**). | 
|  |  | 
|  | ```console | 
|  | $ git checkout master | 
|  | $ git pull --ff-only upstream master | 
|  | $ git push origin | 
|  | ``` | 
|  |  | 
|  | If you do this while you have changes on some other branch then before | 
|  | a Pull Request will work you need to be sure your branch merges | 
|  | cleanly into the new lowRISC repo. Assuming you got the local `master` | 
|  | branch up to date with the procedure above you can now **rebase** your | 
|  | changes on the new `master`. Assuming you have your changes on the local | 
|  | branch `forchange`: | 
|  |  | 
|  | ```console | 
|  | $ git checkout forchange | 
|  | $ git rebase master | 
|  | ``` | 
|  |  | 
|  | If you are lucky this will just work, it unwinds your changes, gets | 
|  | the updated `master` and replays your changes. If there are conflicts | 
|  | then you need a big pot of coffee and patience (see next section). | 
|  |  | 
|  | Once everything has rebased properly you can do | 
|  |  | 
|  |  | 
|  | ```console | 
|  | $ git log | 
|  | ``` | 
|  |  | 
|  | And see that the changes you commited on the branch are at the top of | 
|  | the log followed by the latest changes on the `master` branch. | 
|  |  | 
|  | Note: be mindful about which branch you are working on. | 
|  | If you have added new commits to your local `master` branch, aligning it with `upstream` using `git pull --ff-only` may fail. | 
|  | An alternative is to use `git pull --rebase` in that case, which directly rebases your local `master` branch onto `upstream/master`. | 
|  | Do not use plain `git pull` or `git merge` commands, as they do not preserve a linear commit history. | 
|  | See also [this tutorial](https://www.atlassian.com/git/tutorials/merging-vs-rebasing) to learn more about `git rebase` vs `git merge`. | 
|  |  | 
|  | ## Dealing with conflicts after a rebase | 
|  |  | 
|  | If a rebase fails because of conflicts between your changes and the | 
|  | code you are rebasing to then git will leave your working directories | 
|  | in a bit of a mess and expect you to fix it. Often the conflict is | 
|  | simple (eg you and someone else added a new routine at the same place | 
|  | in the file) and resolution is simple (have both in the new | 
|  | output). Sometimes there is more to untangle if different changes were | 
|  | done to the same routine. In either case git has marked that you are | 
|  | in a conflict state and work is needed before you can go back to using | 
|  | your local git tree as usual. | 
|  |  | 
|  | The git output actually describes what to do (once you are used to how | 
|  | to read it). For example: | 
|  |  | 
|  | ```console | 
|  | $ git rebase master | 
|  | First, rewinding head to replay your work on top of it... | 
|  | Applying: [util][pystyle] Clean Python style in single file tools | 
|  | Using index info to reconstruct a base tree... | 
|  | M       util/diff_generated_util_output.py | 
|  | M       util/build_docs.py | 
|  | Falling back to patching base and 3-way merge... | 
|  | Auto-merging util/build_docs.py | 
|  | CONFLICT (content): Merge conflict in util/build_docs.py | 
|  | Auto-merging util/diff_generated_util_output.py | 
|  | error: Failed to merge in the changes. | 
|  | Patch failed at 0001 [util][pystyle] Clean Python style in single file tools | 
|  | Use 'git am --show-current-patch' to see the failed patch | 
|  |  | 
|  | Resolve all conflicts manually, mark them as resolved with | 
|  | "git add/rm <conflicted_files>", then run "git rebase --continue". | 
|  | You can instead skip this commit: run "git rebase --skip". | 
|  | To abort and get back to the state before "git rebase", run "git rebase --abort". | 
|  | ``` | 
|  |  | 
|  | The last line of this gives the ultimate out. You can abort the rebase | 
|  | and figure some other way to proceed. As it says, this is done with: | 
|  |  | 
|  | ```console | 
|  | $ git rebase --abort | 
|  | ``` | 
|  |  | 
|  | After executing this command you are back to a clean tree with your | 
|  | changes intact, but they are still based on whatever the earlier state | 
|  | of the repository was. Normally you will have to resolve the conflict | 
|  | sometime, but the escape hatch can be useful if you don't have time | 
|  | immediately! | 
|  |  | 
|  | In the normal case, read the output to find the file with the | 
|  | problem. In this case `Merge conflict in util/build_docs.py` (The merge | 
|  | of `util/diff_generated_util_output.py` was successful even though it | 
|  | is mentioned in the middle of what looks like error output.) | 
|  |  | 
|  | If the file is opened with an editor the points at which there are | 
|  | conflicts will have diff-style change information embedded in to them. For example: | 
|  |  | 
|  | ```console | 
|  | <<<<<<< HEAD | 
|  | import livereload | 
|  |  | 
|  | import docgen.generate | 
|  | ======= | 
|  | import docgen | 
|  | import livereload | 
|  | >>>>>>> [util][pystyle] Clean Python style in single file tools | 
|  |  | 
|  | ``` | 
|  |  | 
|  | In this case, the upstream repository's copy of `util/build_docs.py` | 
|  | was modified to import `docgen.generate` rather than just `docgen`. | 
|  | Because git couldn't automatically merge that change with the one | 
|  | we made, it gave up. The code between `<<<<<<< HEAD` and `=======` | 
|  | represents the change in the upstream repository and the code between | 
|  | `=======` and `>>>>>>>` represents the change in our copy. | 
|  |  | 
|  | These lines have to be edited to get the correct merged | 
|  | result and the diff markers removed. There may be multiple points in | 
|  | the file where fixes are needed. Once all conflicts have been | 
|  | addressed the file can be `git add`ed and once all files addressed the | 
|  | rebase continued. | 
|  |  | 
|  |  | 
|  | After the fix a status report will remind you where you are. | 
|  |  | 
|  | ```console | 
|  | $ git status | 
|  | rebase in progress; onto cb85dc4 | 
|  | You are currently rebasing branch 'sastyle' on 'cb85dc4'. | 
|  | (all conflicts fixed: run "git rebase --continue") | 
|  |  | 
|  | Changes to be committed: | 
|  | (use "git reset HEAD <file>..." to unstage) | 
|  |  | 
|  | modified:   diff_generated_util_output.py | 
|  | modified:   build_docs.py | 
|  |  | 
|  | Changes not staged for commit: | 
|  | (use "git add <file>..." to update what will be committed) | 
|  | (use "git checkout -- <file>..." to discard changes in working directory) | 
|  |  | 
|  | modified:   build_docs.py | 
|  |  | 
|  | ``` | 
|  |  | 
|  | This gives the same instructions as the original merge failure message | 
|  | and gives the comfort that all conflicts were fixed. To finish up you | 
|  | need to follow the instructions. | 
|  |  | 
|  | ```console | 
|  | $ git add build_docs.py | 
|  | $ git rebase --continue | 
|  | Applying: [util][pystyle] Clean Python style in single file tools | 
|  | ``` | 
|  |  | 
|  | If there were more than one patch outstanding (which isn't usual if | 
|  | you use the `commit --amend` flow) then you may get subsequent | 
|  | conflicts following the `rebase --continue` as other patches are | 
|  | replayed. | 
|  |  | 
|  | You can check the rebase worked as expected by looking at the log to | 
|  | see your branch is one commit (or more if there were more) ahead of | 
|  | the `master` branch. | 
|  |  | 
|  | ```console | 
|  | $ git log | 
|  |  | 
|  | commit dd8721d2b1529c575c4aef988219fbf2ecd3fd1b (HEAD -> sastyle) | 
|  | Author: Mark Hayter <mark.hayter@gmail.com> | 
|  | Date:   Thu Jan 10 09:41:20 2019 +0000 | 
|  |  | 
|  | [util][pystyle] Clean Python style in single file tools | 
|  |  | 
|  | Result of lintpy.py --fix on the diff and build_docs tools | 
|  |  | 
|  | Tested with  ./diff_generated_util_output.py master | 
|  |  | 
|  | commit cb85dc42199e925ad09c45d33f6483a14764b93e (upstream/master, origin/master, origin/HEAD, master) | 
|  |  | 
|  | ``` | 
|  |  | 
|  | This shows the new commit (`HEAD` of the branch `sastyle`) and the | 
|  | preceding commit is at the `master` branch (and at the same point as | 
|  | `master` on both `origin` and `upstream` so everything is in sync at | 
|  | `master`). | 
|  |  | 
|  | At this point the conflicts have been cleared and the local repository can | 
|  | be used as expected. | 
|  |  | 
|  | You may find it useful to change the default for the way git reports conflicts in a file. See [Take the pain out of git conflict resolution: use diff3](https://blog.nilbus.com/take-the-pain-out-of-git-conflict-resolution-use-diff3/) | 
|  |  | 
|  | ## Downloading a pull request to our local repo | 
|  |  | 
|  | With the commands below, you can checkout a pull request from the upstream repository to | 
|  | your local repo. | 
|  |  | 
|  | ```console | 
|  | $ git fetch upstream pull/{ID}/head:{BRANCH_NAME} | 
|  | $ # e.g. git fetch upstream pull/5/head:docgen_review | 
|  | $ git checkout {BRANCH_NAME} | 
|  | ``` | 
|  |  | 
|  | ### Applying the pull request to the local commit | 
|  |  | 
|  | In some cases, you might need to apply a pull request on top of your local commits. | 
|  | For instance, if one user prepares a verification test case and finds a bug. | 
|  | Another user fixed it and created a pull request. The first user needs | 
|  | to test if the fix works on the new verification environment. | 
|  |  | 
|  | In this case, it is recommanded to create a new branch on top of the local | 
|  | commit and `rebase`, `cherry-pick`, or `merge` the pull request. Assume you have a branch | 
|  | name 'br_localfix' which has an update for the verification environment. If the | 
|  | other user created a pull request with ID #345, which has a fix for the | 
|  | design bug, then you can apply the pull request into new branch | 
|  | 'br_localandremote' with the following three methods: | 
|  |  | 
|  | * The `rebase` method: | 
|  |  | 
|  | ```console | 
|  | $ git checkout -b br_localandremote br_localfix | 
|  | $ git fetch upstream pull/345/head:pr_345 | 
|  | $ git rebase pr_345 | 
|  | ``` | 
|  |  | 
|  | * The `cherry-pick` method: | 
|  |  | 
|  | ```console | 
|  | $ git checkout -b br_localandremote br_localfix | 
|  | $ git fetch upstream pull/345/head:pr_345 | 
|  | $ # find the commit ID from pr_345 that you want to merge: b345232342ff | 
|  | $ git cherry-pick b345232342ff | 
|  | ``` | 
|  | * The `merge` method: | 
|  |  | 
|  | ```console | 
|  | $ git fetch upstream pull/345/head:pr_345 | 
|  | $ git checkout -b br_localandremote br_localfix | 
|  | $ git merge pr_345 | 
|  | ``` | 
|  |  | 
|  | The `rebase` method is more convenient than `cherry-pick` if you have more | 
|  | than one commit ID to merge. The `merge` method can only be used for local | 
|  | testing as the upstream lowRISC repository does not allow merge commits. | 
|  | Sometimes, applying other contributor's pull request can result in conflicts | 
|  | if both commits have the same change. In that case, you should resolve the conflicts | 
|  | and continue the merge. Section [Dealing with conflicts after a rebase](#dealing-with-conflicts-after-a-rebase) | 
|  | has detailed guidance on how to solve conflicts. | 
|  |  | 
|  | ## Creating updates on top of a pending pull request | 
|  |  | 
|  | In some cases, you might want to directly change other contributor's pull | 
|  | request. The process is quite complicated so please follow the instruction below | 
|  | step-by-step with caution: | 
|  |  | 
|  | * Step 1: Checkout the other pull request branch | 
|  |  | 
|  | ```console | 
|  | $ git fetch upstream pull/{ID}/head:{BRANCH_NAME} | 
|  | $ git checkout {BRANCH_NAME} | 
|  | ``` | 
|  |  | 
|  | * Step 2: Make necessary changes | 
|  |  | 
|  | ```console | 
|  | $ git add... | 
|  | $ git commit -m "Add CFG examples to UART specification" | 
|  | ``` | 
|  |  | 
|  | * Step 3: Create your GitHub branch for the pull request | 
|  |  | 
|  | ```console | 
|  | $ git push -u origin {BRANCH_NAME}:<remote_branch_name> | 
|  | ``` | 
|  |  | 
|  | You can use any branch name for the pull request. | 
|  | If you want to the created branch name same as local branch name, this can | 
|  | simply be: | 
|  |  | 
|  | ```console | 
|  | $ git push -u origin HEAD | 
|  | ``` | 
|  |  | 
|  | * Step 4: Create a pull request into the other contributor's forked repository | 
|  |  | 
|  | To create a pull request in other's forked repository, you can follow the same method | 
|  | as creating a pull request as section [Working in your local | 
|  | repo](#working-in-your-local-repo) explained in details. | 
|  | Once the other contributor's pull request is merged into the upstream | 
|  | repository, you will need to create a pull request in that upstream repository | 
|  | instead. | 
|  |  | 
|  | These are all the steps needed. Once your pull request is reviewed and merged, you will | 
|  | be able to see that the commit is also visible in the original pull request. |