###### tags: `Students`
# Git Workflows
These samples use Ramp 4 repo but can be swapped for anything. They also assume the standard team working branch is `main`. This can change from project to project (e.g. in Ramp 2, `main` is called `master` only contains released commits and the working branch is `develop` ).
[Generic GIT Cheat Sheet](https://wizardzines.com/git-cheat-sheet.pdf) if ya want it.
## Initial Setup
Be logged in to your github account in your browser.
### Fork the Team Repo
Go to the [team repo](https://github.com/ramp4-pcar4/ramp4-pcar4). In the upper right of the page, click the `Fork` button. Fork it to your personal github account.
The browser will likely redirect to the repo on your own github. If not, browse to your repo homepage.
### Clone Your Repo
You can grab the github repo url from the `Code` button dropdown. On your command line, clone your repo to your hard drive.
```
$ git clone https://github.com/yourGithubID/ramp4-pcar4.git
```
This will put the repo contents in a subfolder with the repo name. All following commands assume the current directory is in that folder (i.e. you probably need to rock a `cd ramp4-pcar4` if you just cloned).
### Set Up Remotes
The clone step above will create a remote called `origin`, pointing to your repo. Add a second remote to point to the team's repo, called `upstream`. Do a fetch to make them shake hands
```
$ git remote add upstream https://github.com/ramp4-pcar4/ramp4-pcar4.git
$ git fetch upstream
```
## Starting a New Batch of Work
### Synch and Branch
Ensure your local main branch is up to date with the team's repo, then create a new branch for the batch of work. Pick an appropriate branch name instead of `mynewbranch`. The branch name is used for making the PR demo URL, so avoid any URL-sensitive characters like `#`, `?`, `&`.
```
$ git checkout main
$ git pull --ff-only upstream main
$ git checkout -b mynewbranch
```
The `--ff-only` flag instructs the pull to abort if it encounters a scenario that would trigger a merge on your local repo. Since the team uses the `rebase` approach to commits, this should never occur; the flag will protect you if someone else breaks the rules.
The `-b` flag instruct the checkout command to first make a new branch, then check it out. Alternately you can do
```
$ git branch mynewbranch
$ git checkout mynewbranch
```
### Code and Commit
Write some amazing code. Test it if you really want to go wild. Once pleased, you need to stage the files you want to commit. If using VS Code, this can be done by clicking the `Source Control` view on the left side-bar, and clicking the `+` button (called "Stage Changes" on the tooltip) for each file you want in the commit. Alternately you can do this in the command line.
To stage individual files
```
$ git add full/path/to/file1.ts
$ git add full/path/to/file2.json
```
To stage all files
```
$ git add .
```
Once everything is staged, do a commit. The message should be to the point and not overly long (100 char max, shorter is better).
```
$ git commit -m 'enhanced duck icon'
```
For larger efforts, it's fine to have multiple commits in one batch of work.
## Submitting a Pull Request
Once you think your code is great, it is time to see if the team agrees. Submitting a pull request (PR) gives your buddies the chance to tear your hard work to shreds.
> Secret hint: if you're in the middle of development and are trying something you're not quite sure is a good idea, it's usually better to raise it as a discussion on one of the chats instead of doing the work of implementing it and then finding out it is hot trash.
### Push and Pull
Send your commits to your personal github repo.
```
$ git push origin mynewbranch
```
> Another secret hint: you can do this with commits of half finished work as a form of backing up your code. If your hard drive dies, you will have your last push available for re-cloning on your github. This doc will cover how to clean up the partial commits later on.
Visit the github page of the [Team's repo](https://github.com/ramp4-pcar4/ramp4-pcar4). If you do this within a few minutes of your push, github will present a friendly option at the top of the page offering to open a PR on your latest push. Otherwise, go to the `Pull Request` tab and select the `New Pull Request` button.
In the pull request body, describe what you have fixed, how to test it (if applicable), and paste a link to any related issue if any. Avoid using the keywords before the issue links that will cause github to close the issue when the PR is finished. We generally keep issues open until release, or until QA has validated the fix. The keywords to avoid are
- `close`, `closes`, `closed`
- `fix`, `fixes`, `fixed`
- `resolve`, `resolves`, `resolved`
Be sure to look at the changes being included in the PR (shown below the description text box). If you see code / files that you did not change, then something went funky on your branch and you will need to clean it up.
Once satisfied, assign anyone you really want to review, and submit the PR.
A few seconds after submitting, a link to [Reviewable](https://reviewable.io) will appear in the PR. This is the platform we use to do code reviews. Monitor the page for any feedback or change requests from your teammates.
### Making Corrections
If someone asks for a correction or change to your active PR, you can make another commit on your branch and simply push it to your personal github repo branch. Github and reviewable will pick up the change. Be sure to reply "Donethanks" to the request so they know to review and hopefully close the request.
Below we will explore how to squish minor changes into previous commits, and how to deal with conflicting changes from teammates.
## Rebase Magic
The `rebase` command lets you wrassle git commits and branches into a state that appeases you. You can even push rebased content to an active pull request, github and reviewable are smart enough to figure out what is going on.
### Clean Up Commits on Your Branch
There can be good reasons to clean up commits on your branch. Some examples:
- You have been doing partial commits on large changes so you could back them up on github. Now you are done and want to combine them into one commit.
- You noticed a spelling mistake and don't want a commit that just corrects one character.
- You want to change a commit message.
> WARNING. Do not adjust any commits that already exist on the team's main branch (`main` for RAMP 4). Doing this will wreck everything. Only adjust commits you have made on your working branch. This also means you should not do rebases on your local main branch.
To do this, figure out how many commits from the head of the current branch you want to adjust. Lets assume we want to adjust the last three commits we made. The last commit is a small mistake correction, and we don't like the message on the 3rd last commit.
```
$ git rebase -i HEAD~3
```
The `HEAD~3` means take the last three commits made on the current branch. The rebase will begin. A text editor will launch and present you with a list of the commits, and comments that outline what commands can be applied to each commit.
```
pick c328d0bdf commit comment xxx
pick ab2042154 commit comment yyy
pick 3e88fa800 corrected a boo boo
# comments and instructions
# .....
```
In the text editor, adjust the commands to your liking. For our example, we would edit to
```
reword c328d0bdf commit comment xxx
pick ab2042154 commit comment yyy
fixup 3e88fa800 corrected a boo boo
# comments and instructions
# .....
```
**Save the text file**, and close the editor. The rebase will continue on. Depending on the commands chosen, another text editor might appear (it will in this case, to allow us to adjust our comment on the `reword` request). It may also pause the rebase for more complex actions like an `edit` request.
After this rebase is done, our commits will look something like this.
```
d39f136ee my better commit comment
4a97743da commit comment yyy
```
The changes in the correction commit are now contained in the `yyy` commit.
Notice the hash values are different than before the rebase. Rebasing re-writes history so new hash values are generated. If our branch has already been pushed to our personal github repo, we need to do a force push (`-f`) to ensure the github branch is updated with our new history and the old history is paved over.
```
$ git push -f origin mynewbranch
```
### Incorporate New Changes from the Team Repo
You have been working, commiting on your branch, maybe even part-way through a PR, and suddenly a teammate has their commits accepted into the team repo. Now your working branch is out of date compared to the team's `main` branch. How rude!
Using rebase you can get your branch re-aligned with `main`, and it will appear as if you started your work *after* your teammates commits existed. Before doing these steps, commit any un-commited work you have on your working branch. You can always clean it up later using the steps in the above section.
```
$ git checkout main
$ git pull --ff-only upstream main
$ git checkout mynewbranch
$ git rebase main
```
In most cases, the rebase will run smoothly. If the incoming new commits are on the same lines of code that you have been working on, the rebase will pause and let you resolve any conflicts in your code editor. Resolve the conflicts, save the files, stage the changed files, then type `git rebase --continue` to carry on. If things look dire during one of these pauses you can always type `git rebase --abort` to stop and undo the rebase.
As above, doing this re-writes the history for any new commits that were on your working branch, so you may need to do a force push to your personal github branch.
### More Rebase Reading
- See: [Git Branching - Rebasing](https://git-scm.com/book/en/v2/Git-Branching-Rebasing)
- See: [Merging vs. Rebasing](https://www.atlassian.com/git/tutorials/merging-vs-rebasing)
- See: [A Rebase Workflow for Git](https://randyfay.com/content/rebase-workflow-git)
## Haaalp I Have Wrecked Everything
### My Uncommited Code is Awful, Go Back to the Last Commit
```
$ git checkout .
```
This will discard any uncommited changes to any files that are under git's pervue.
### My Branch is Broken, I Want It To Look Like the Branch on Github
This is a dangerous command, make sure you know what you're doing first.
Lets say you have corrupted your `main` branch on your local repo, and want it to look like the team's `main` branch.
```
$ git checkout main
$ git reset --hard upstream/main
```
The remote name and branch name can be adjusted as you please.