Git のすごくすごく簡単なまとめ

# callmekohei's Git memo
`Git`のちょっとしたまとめ

## Environment

```bash
$ sw_vers 
ProductName:	Mac OS X
ProductVersion:	10.13.5
BuildVersion:	17F77
```

## Prepare

install commands

```bash
$ brew install git
$ brew install hub
$ brew install gibo
```

bashrc ( $HOME/.bashrc )

```bash
# alias
eval "$(hub alias -s)"

# completion
source /usr/local/etc/bash_completion.d/git-completion.bash
source /usr/local/etc/bash_completion.d/hub.bash_completion.sh
```

config file ( $HOME/.gitconfig )

```bash
[user]
    name  = callmekohei
    email = callmekohei@gmail.com
[merge]
    # fast-forward merge をしない
    # topic branch の履歴をあえて残す
    ff = falsea 
    tool=vimdiff
[pull]
    rebase = true
    ff = only
```

ssh ( for Github )
[Generating a new SSH key and adding it to the ssh-agent](https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/)
[Adding a new SSH key to your GitHub account](https://help.github.com/articles/adding-a-new-ssh-key-to-your-github-account/)


## 用語
Git has three situations.

```text
working directory ( work tree , working copy )
staging area ( index )
repository
```

## Gitの使い方

1. `topic branch`を作成してコードを書き、いい感じなったら`master`にマージ
2. `git reset`, `git checkout foo.txt` するときは、`git stash` を実行すること
3. 文字コード/改行コードの変更とコードの変更を一緒にコミットしない！
4. `push -f` は極力使わない！
5. コミットメッセージは具体的に書く！

```text
x  バグ修正
▲ fooのタイムアウト値を500msから1000msに変更
○ fooフィールドに値がない場合にエラーになるバグを修正
```

## .git

gitとは？

```text
git add      は file の追加
git commit   は ファイル構成の追加
id は 160bit の SHA-1 を使ってるのでダブらない
```

git add foo.txt

```text
.git/index  に indexデーターを追加（tree objを作るのに必要）
.git/objectsに blob objを追加（blob obj = real date）
```

git commit -m 'foo'

```text
.git/objectsにtree objを追加（tree obj = ファイル構成(folder) ）
.git/objectsにcommit objを追加（commit obj contains tree obj and previous commit id )
```

確認用commands

```bash
# index ファイルをみる
$ git ls-files -s

# objects ファイルをみる（ -t:type, -s:size, -p:value ）
$ git cat-file -p commit-id

# commited objects ファイルをみる
$ git rev-list --all --objects --format=oneline
```

## add, commit and rollback

rollback ( file指定 -> checkout )

```
        wt         idx         repo
 -----------------------------------------+ checkout HEAD foo.txt
            checkout foo.txt              | reset --hard HEAD
        *   <---    *           *         | <--+  <--+
   edit |                                 |    |     |
        v                                 |    |     |
        @           *           *         |    |     |
                    ^                     |    |     |
            add     | reset               |    |     |
        @   --->    @           *         | ---+     |
                                ^ reset   |    checkout HEAD^ foo.txt
                        commit  | --soft  |    reset --hard HEAD^
        @           @   --->    @         | ---------+ 
```

counter command

```
add    <-> reset
commit <-> reset --soft HEAD^
```

rollback in Github

```shell
# 相殺コマンド（履歴が残る）
$ git revert commit-id
```

commit id

```text
abs
    3a0d708
relative
    head~ head~2 head~3 ( before  )
    head^ head^2 head^3 ( parents )
```


## git commands

なにはともあれ一時保存`stash`
`stash`したときは`commit`した状態にもどる

```bash
# 一時保存 stash save --include-untracked
$ git stash-all

# 一時保存リスト
$ git stash list

# 一時保存した状態にする
$ git stash apply <tab>

# stashをけす
$ git stash drop <tab>
```

状況確認`show, log, reflog`

```bash
# 今の状況を見る show -sb
$ git s

# コミット状況を見る log --graph --all --oneline --decorate -n 20
$ git tree

# commit id を見る
$ git reflog
```

変更箇所を見る`diff, show`

```bash
# git add する前に差分を見る diff
$ git d foo.txt

# git add した後に差分を見る diff --staged
$ git ds foo.txt

# commitの差分を見る !git log --oneline | fzf | cut -d ' ' -f1 | xargs -o git show
$ git dp
```

インデックスに変更を追加 `add`

```shell
# ファイル構成を変えた時は実施
$ git add -A

# 細かくインデックスに追加
$ git add -p ( use e )

# stage させない方法
    +foo " ラインを消す
    -foo " - を space にかえる

# エラーがでるときはこれを消す
    @@ -1,4 +1,6 @@ 
```

コミットを作成 `commit`

```bash
$ git commit -m 'foo' foo.txt
```

今いるコミット(HEAD commit)に何かする `commit --amend`

```bash
$ git commit --amend -m 'bar' foo.txt
```

コミットを分割する `rebase, edit`

```bash
$ git rebase -i commit-id

        pick 6f095c6 foo
        edit 04c02fd bar
        pick 1f16754 baz

    $ git reset HEAD^
    $ git add -p
    $ git commit -m 'bar 01'
    $ git add -p
    $ git commit -m 'bar 02'

$ git rebase --contine
```

コミットを編集する `rebase, edit`

`conflict`が起こった場合は競合箇所を修正してからaddとrebase --continueを実行（コミットはしない）

```bash
$ git rebase -i commit-id

        pick 6f095c6 foo
        edit 04c02fd bar
        pick 1f16754 baz

    $ vim foo.txt
    $ git add foo.txt
    $ git commit --amend

$ git rebase --continue
```

コメントを変更する `amend, rebase, reword`

```bash
# 直前のコミットメッセージの変更
$ git commit --amend -m 'foo'
```

（順序を変えて）コミットをまとめる `rebase, fixup, squash`

```vim
" 順序を変える場合はコミット行を入れ替える
" コメントを変更する場合は squash
pick   foo
fixup  bar
```

コミットを削除する `rebase`

```
削除したいコミットの行を消す
```

ブランチを作成 `branch`

```shell
$ git branch foo

# 過去のcommit-idから分岐させる
$ git checkout commit-id  # HEADを移動させて・・
$ git branch foo          # そこからブランチをきる
```

ブランチをけす `delete`

```shell
# local
$ git branch --delete foo

# remote
$ git push --delete origin foo

# remote
$ git fetch --prune
```

ブランチの切り替え `checkout`

```shell
# ブランチの確認
$ git branch -a

# ブランチの切り替え local
$ git checkout foo

# ブランチの切り替え remote
$ git checkout origin foo
$ git pull origin foo
```

ブランチをmasterにとりこむ `merge`

```shell
$ git checkout master
$ git merge foo
```

merge conflict `ours, theirs and manual edit`

```shell
# use ours theirs
$ git checkout --ours foo.txt
$ git checkout --theirs foo.text

# manual edit
$ git difftool foo.txt
```

## Github ( TODO: よくわかってない ）

`origin` shows `Github` repository

他の人へのプルリク

```bash
# Githubでfork

# forkしたリポジトリをダウンロード
$ git clone <web address>

# ブランチをきる
$ git checkout -b foo

# ブランチfooをアップロード
$ git push -u origin foo

# Githubでプルリク
```

自分のリポジトリ

```bash
# Github's repository ( origin ) を作成
$ git create

# upload
$ git push

# upload foo branch
$ git branch -b foo
$ git push

# プルリク
$ git pull-request -b master foo
```

## Reference

[Pro Git](https://git-scm.com/book/ja/v2)
[サルでもわかるGit入門](https://backlog.com/ja/git-tutorial/)
[Gitポケットリファレンス](https://www.amazon.co.jp/%E3%80%90%E6%94%B9%E8%A8%82%E6%96%B0%E7%89%88%E3%80%91Git%E3%83%9D%E3%82%B1%E3%83%83%E3%83%88%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9-%E5%B2%A1%E6%9C%AC-%E9%9A%86%E5%8F%B2/dp/4774185930)
[GitHub実践入門](https://www.amazon.co.jp/GitHub%E5%AE%9F%E8%B7%B5%E5%85%A5%E9%96%80-Pull-Request%E3%81%AB%E3%82%88%E3%82%8B%E9%96%8B%E7%99%BA%E3%81%AE%E5%A4%89%E9%9D%A9-PRESS-plus/dp/477416366X)
[Web制作者のためのGit入門](https://www.amazon.co.jp/Web%E5%88%B6%E4%BD%9C%E8%80%85%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AEGit%E5%85%A5%E9%96%80-Mynavi-Advanced-Library-%E5%A4%A7%E6%9D%89/dp/4839952027)
[アリスとボブのGit入門レッスン](https://www.amazon.co.jp/%E3%82%A2%E3%83%AA%E3%82%B9%E3%81%A8%E3%83%9C%E3%83%96%E3%81%AEGit%E5%85%A5%E9%96%80%E3%83%AC%E3%83%83%E3%82%B9%E3%83%B3-%E5%B7%9D%E9%87%8E%E8%BE%BA-%E6%AD%A3%E5%8D%9A/dp/4798035009)