Git攻略ガイド

初心者がコマンド方面でGit攻略するための道標を考えてみた。
見落としそうなものを集めてみた。
説明が少ないかもしれないがキーワードから検索してたどって欲しい。

# 道標

## 初心者～

- 原典の[git-scm](https://git-scm.com/book/ja/v2)を読む。原典以外の説明はすべて素人が書いた劣化コピーにすぎない。ユーザー名とEmailアドレスを設定することも書いてある。
- `git help コマンド`を使う。ブラウザにヘルプが立ち上がる。ヘルプを読む。
- GUIソフトを使う(SmartGitなど)。
- GUIソフトとコマンドプロンプトを交互に使う。交互に使うと学ぶことが多い。
- テスト用のレポジトリを作るための初期化コマンド（後述）を作る。
- テスト用のレポジトリを作って知らないコマンドを試す。
- レポジトリのフォルダーで毎回`git status`（ステータス表示）を使う。どういうときにどのように表示されるかを理解する。
- レポジトリのフォルダーで毎回`git log`（ログ表示）を使う。最近の履歴などを把握する。`--all`を付けるとすべてのタグとブランチが表示される(dangling commitは表示されない)。
- Bashのalias（後述）を使う。基本の`st`をよく使う。
- Gitのalias（後述）を使う。
- 表示コマンドの`git branch`や`remote`や`ls-files`に`-vv`を付ける。コマンドを試した結果を表示させないとコマンドの意味を理解できないことがある。
- 表示コマンドの`git tag`に`-n`を付ける。
- `@~3..@`の意味を知る(HEADの3つ親からHEADまでの略）。
- GitHubにレポジトリを作ってプッシュしてみる。
- .gitignoreを使う。

## 中級者～

- `git push -f` でなく `--force-with-lease` を使う。
- GitHub上の優秀なレポジトリを探す。クローンしてGUIソフトで眺めると学べることがある。
- Angular.jsのコミットメッセージのフォーマット（後述）を使う。
- commit.templateにコミットメッセージのフォーマットを設定する。
- `git commit`は`-m "メッセージ"`を使わず使い慣れたテキストエディターを立ち上げてコミットメッセージを入力する。git configの`core.editor`。
- Windows使用者はGitコマンドからWinMergeを呼び出して差分を見る。
- HEADやブランチを自在に移動する。`git checkout -f`や`git reset --hard`や`git merge`や`git branch -m`(名前変更)や`git tag`(名前付与)など。

## 上級者～

- コミットメッセージにbodyを付ける。
- テキストの改行コードCRLFとLFを学ぶ。改行コードが異なる人たちがどのように合わせているか。`core.autocrlf`や`.gitattributes`。
- 【初心者危険】rootだけrebaseできないようになっているがrootからのrebaseを使ってみる。`git rebase --root -i`。
- 【初心者危険】gcを使ってdanglingコミットを永久削除してみる。`git reflog expire --expire=now --all; git gc --aggressive --prune=now`。
- GitでWordの差分を見てみる。
- GitHubでフォークしてプルリクエストを投げてみる。


# Angular.jsのコミットメッセージのフォーマット

原典は[ここ](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#user-content-commit-message-format)にある。
簡単に日本語訳してみた。

```
<type>(<scope>): <subject>
<空行>
<body>
<空行>
<footer>
```

- revertのとき

```
revert: fix(Angular): add workaround for Safari / Webdriver problem
```

のように書く。
bodyでは

```
This reverts commit 6b915ad9db29027e0aa70634e08a8a3c5af897b8.
```

のように元に戻されるコミットのSHAを書く。

- Typeは次のどれか

```
feat: 新機能
fix: バグ修正
docs: ドキュメントのみの変更
style: コードの意味に影響を与えない変更（空白、フォーマット、セミコロンの欠落など）
refactor: バグを修正も機能も追加しないコード変更
perf: パフォーマンスを向上させるコード変更
test: 欠けているテストや既存のテストを修正する
chore: ビルドプロセスあるいは文書生成などの補助ツールやライブラリーの変更
```

- Scopeはコミット変更の場所を指定するものなら何でもいい。*は変更が複数のスコープに影響を与える場合に使う。
- Subjectは頭を大文字にしない、末尾に.を付けないなど。
- Bodyは本文。
- フッターはBREAKING CHANGE:(重大な変更)を書いたりこのコミットが閉じるGitHubの問題を参照する場所。


# Alias

## Bashのalias

```bash

alias st='git status'
alias l2='git log2'
```

## Gitのalias

```bash

alias.log2=log --graph --date=iso-local --format="%x09%C(yellow)%h%C(reset) %C(magenta)[%ad]%C(reset)%C(auto)%d%C(reset) %s %C(cyan)@%an%C(reset)"
```


# テスト用のレポジトリを作るための初期化コマンド

<details><summary>例１、短い、全タグ</summary><div>


```bash

git init
echo a0 > a.txt; git add -A; git commit -am "初期化 a0"; git tag a0;
echo a1 > a.txt; git add -A; git commit -am "変更 a1"; git tag a1;
echo a2 > a.txt; git add -A; git commit -am "変更 a2"; git tag a2;
git status
```

</div></details>

<details><summary>例2、少し長い、単純、全タグ</summary><div>

```bash

git init;
echo a0 > a.txt; git add -A; git commit -am "初期化 a0"; git tag a0;
git config user.name "Linus Torvaldss"
git config user.email torvaldss@linux-foundationn.org
echo b0 > b.txt; git add -A; git commit -am "初期化 b0"; git tag b0;
echo b1 > b.txt; git add -A; git commit -am "変更 b1"; git tag b1;
echo b2 > b.txt; git add -A; git commit -am "変更 b2"; git tag b2;
git config --unset user.name
git config --unset user.email
git checkout -b develop a0;
echo a1 > a.txt; git add -A; git commit -am "変更 a1"; git tag a1;
echo a2 > a.txt; git add -A; git commit -am "変更 a2"; git tag a2;
git status
```

</div></details>

<details><summary>例3、少し長い、複雑、全タグ</summary><div>

```bash

git init;
echo c0 > c.txt; git add -A; git commit -am "初期化 c0"; git tag c0;
echo c1 > c.txt; git add -A; git commit -am "変更 c1"; git tag c1;
echo c2 > c.txt; git add -A; git commit -am "変更 c2"; git tag c2;
git checkout -b server;
echo c3 > c.txt; git add -A; git commit -am "変更 c3"; git tag c3;
echo c4 > c.txt; git add -A; git commit -am "変更 c4"; git tag c4;
git checkout master;
echo c5 > c.txt; git add -A; git commit -am "変更 c5"; git tag c5;
echo c6 > c.txt; git add -A; git commit -am "変更 c6"; git tag c6;
git checkout -b client c3;
echo c8 > c.txt; git add -A; git commit -am "変更 c8"; git tag c8;
echo c9 > c.txt; git add -A; git commit -am "変更 c9"; git tag c9;
git checkout server;
echo c10 > c.txt; git add -A; git commit -am "変更 c10"; git tag c10;
git status
```

![図 3-31. トピックブランチからさらにトピックブランチを作成した歴史](https://git-scm.com/figures/18333fig0331-tn.png) [^pic]

</div></details>

コマンドを使ってみないと理解できない。
コマンドの種類もオプションも非常に多いのでヘルプを見る癖をつけよう。


# Gitコマンドを一言で紹介してみる

## add

ステージに上げる。
よく使う。

## bisect

二分探索して問題箇所を見つける。

## blame

誰がどの行を直したか。

## branch

言葉で説明できないので体で覚えるのみ。
ブランチ。リモート追跡ブランチ。上流ブランチ。

## checkout

ブランチを切り替えるかワーキングツリーのファイルを復旧。
言葉で説明できないので下手な直訳で逃げた。

## cherry-pick

指定コミットを1つあてる。

## clone

クローン人間でなくクローンレポジトリ。

## commit

言葉で説明できないので体で覚えるのみ。
コミットする。

## config

Alias(別名)などの設定値。

## diff

ファイルの差分。
ステージに上がったら--stagedで。

## difftool

WinMergeなどの外部の神ツールで差分を見る。

## fetch

リモートレポジトリから最新情報を取ってくる。

## for-each-ref

クローンしたのにブランチがないときリモートブランチ(refs/remotes)を見れる。

## fsck

データベース検査。

## log

コミットログの表示。
よく使う。

## ls-files

-vvでファイルの管理状態か。

## merge

言葉で説明できないので体で覚えるのみ。
HEADを移動したりマージしたり。

## push

リモートレポジトリに倍プッシュだ。
不安な人は-nしてから。

## rebase

２つの使い方。
-iで対話するかcherry-pickを一気にやるか。

## reflog

操作履歴か。

## remote

リモートリポジトリに関する設定。

## reset

ファイルを変更しないでHEADの位置を変える。
--hardならファイル変更。

## revert

変更を打ち消す。

## show

昔のファイルの中身を表示。

## stash

`git add -A; git commit; git tag stash01; git reset --hard @~1;`と同義か。
使わないので知らない。

## tag

コミットに名前をつける。


[^pic]: [git-scm.comの説明で使用されたブランチの図。初期化コマンドの例3の中。](https://git-scm.com/book/ja/v1/Git-のブランチ機能-リベース#さらに興味深いリベース)