Rules of Git and GitHub for our team

# 1. Basis

## 1-1. First of all

Check the "push mode" of your Git.

```bash
git config --global push.default
```

It doesn't show anything? It's fine. If it shows something other than "simple", let me know.


## 1-2. GitHub Flow

We follow GitHub Flow. Read through the page below.
https://guides.github.com/introduction/flow/
\* Note that the contents are in a slider UI, so don't miss them.


If you have some experience of Git Flow and if you are curious about the difference between Git Flow and GitHub Flow (those two are very different), I recommend this. (But it's not necessary.)
http://scottchacon.com/2011/08/31/github-flow.html

The points of GitHub Flow are:

- Always make a branch from `master`.
- Keep branches, Pull Requests (PR) and tasks as small as possible.
- Commit often. Push often. And make a PR right after you push your first commit.
    - You can make a PR before you finish your task. The sooner the better.

### One thing that is different from GitHub Flow

With our rule, after you finish your task, you will merge your branch to `master` and deploy `master`.

With GitHub Flow, a developer will merge `master` to his/her branch and deploy the branch (not `master`). After that, the developer will merge the branch to `master`.


## 1-3. Never do this

Never use `--force` (or `-f`) option when you use `git push`.

\* Actually I've already configured our GitHub repositories so that you can't use `git push --force` to `master`. But don't even use `--force` to any other branches also.


# 2. Our actual flow

## 2-1. Make a branch and a PR

Make a branch and checkout it from the latest `master`.

```bash
git checkout master
git pull # Update `master` on your local
git checkout -b my-branch
```

After you commit some codes, push it right away to GitHub. Commit often, push often is one of the GitHub ways.

```bash
git push origin my-branch
```

If you push with `--set-upstream` (or `-u`) option,

```bash
git push --set-upstream origin my-branch
```

then you can skip typing your branch name afterwards.

```bash
git push
```

Now you can (should) make a PR in GitHub and write the PR URL in the Trello card you are working with. Again I recommend you that you make a PR as soon as possible.

### Make a PR with no changes

Some people make PRs even without changing anything. But you need to have at least one commit to do so. You can do this with an empty commit using `--allow-empty` option.

```bash
git commit --allow-empty -m "Your commit message here"
```

This is just a tip and it's not mandatory for our team. Anyway please think that a PR is like a web bulletin board. And you can open it or close it whenever you want.



## 2-2. Merge and deploy your branch

You can merge your PR by yourself without code review if the branch only includes text, HTML, CSS changes or some small PHP changes.

If you think the PHP changes are somewhat big, ask someone to review your code.

Don't forget to click the "Delete branch" button on GitHub after you merge or close your PR.

<img width="784" alt="68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f3837342f66353765636564382d343363342d383332382d613766332d6639363864633032623337342e706e67.png" src="https://qiita-image-store.s3.amazonaws.com/0/874/68348f05-0167-1bcc-006e-91cd4125a779.png">


Next, update `master` on your local.

```bash
git checkout master
git pull
```

Then you will be able to delete your branch.

```bash
git branch -d my-branch
```

Now you can deploy `master` to our production servers.


## 2-3. Get someone else's PR to your local

When you review someone else's PR, normally you do it on the GitHub web pages. However, sometimes you will want to get the PR to your local. Or sometimes you will need to work on the PR with other developers.

First, update branches on your local with `git fetch` with `--prune` (or `-p`) option. The option will delete your local branches if they have been deleted on remote (= GitHub), so always use `--prune` option.

```bash
git fetch --prune
```

Check if you have successfully updated every branches on your local.

```bash
git branch --all # Or you can use `-a` instead.
```

Next, checkout the remote branch to your local.

```bash
# You can also do it only with `git checkout someone-branch`.
# It's the shortcut, same as the command below.
git checkout remotes/origin/someone-branch -b someone-branch
```

Now you can pull/push without the branch name.

```bash
git pull
git push
```

## 2-4. Undo what you have done

### Undo what you have added

You can do it with this.

```bash
git reset
```

If you pass a commit ID parameter to `git reset`, you can change our Git history. But don't do this. If you want to change or undo what you have committed, read the following.

### Undo what you have committed

It's so easy. Just **manually write codes and commit them** that can undo what you have done.

If it's a pain in the neck to write such codes, you can use `git revert`. But be careful when you use `git revert`.

When you just want to change the commit message that you've just written, for example when you misspelled, you can do with `--amend` option.

```bash
git commit --amend -m "New commit message"
```


# 3. Other useful Git commands

## git diff

With `git diff`, you can check the difference between your working directory and what you added. With `git diff HEAD`, you can check the difference between your working directory and `HEAD`. (Normally, `HEAD` is the newest commit that you or someone made in your current branch).

By the way, I recommend that you use `-b` option instead of `-w` option when you want to ignore whitespace changes. Look this diff. Someone accidentally put a white space between `/` and `usr`. What a fiasco!

```diff
-sudo rm -rf /usr/local/bin/abc
+sudo rm -rf / usr/local/bin/abc
```

`-w` option ignores all whitespace changes so you **won't** see the diff above.
`-b` option only ignores changes only when the amount of whitespaces changed. For example, 2 spaces to 3, or 3 to 2, will be ignored. But 1 to 0, or 0 to 1, won't be ignored. So you will be able to spot the diff above.


## git grep

I use this command a thousand times a day. I believe `grep` is the best tool on earth. Without this, I would quit my job and become a Uber driver.

`-i` option ignores upper and lower cases. `-I` option ignores differences in binary files.


## git blame

This command is useful when you want to know who wrote a line of codes.

```bash
git blame [file]
```

Remember that `git blame` is not for "blaming" anyone. It's just for knowing the person who wrote the line especially when you want to ask him/her something about the code.



## git log

The following command shows every commits with a neat graph view.

```bash
git log --all --graph --oneline
```

If you don't want to bother typing the command above many times a day, just set an alias in `~/.gitconfig`.

```ini
[alias]
    tree = log --all --graph --oneline
```

Now you can call the alias with this.

```bash
git tree
```