初心者のGitメモ

素人プログラマの自分用メモです。
あわよくば他の初心者の役に立てば。あわよくば心優しい達人からのフィードバックを頂戴できれば。という下心を抱きつつ。

順番には意味はなく、書きたいものを書きたい順に。（今後も学んだことを書き足していきたい。）

# git reset について

add しちゃったけど、取り消したいときに使えます。

```zsh
git reset HEAD
```

と、すればaddを取り消してくれます。正確には、インデックスの状態をHEADと同じにしてくれる。`--soft`や`--hard`というオプションもある。詳しくはこちら
「murankの日記」
http://d.hatena.ne.jp/murank/20110327/1301224770
とても分かりやすいです。有り難うございます。

ちなみに、僕のいじってみたところでは、First commitをする前だと、`git add HEAD`が動かず。**（これ分からないのですが、First commit前だと効かないのですか？）**

```zsh
git reset HEAD -- .
```
などとしました。

`--`の後ろはファイル名で良いと思うのですが（`-- <file>`のように 半角スペース必要）、全部リセットしたかったので、`.`としています。`*`とすれば、ドットファイル以外を全部指定します。

**ちなみに、`--`だけでも全部リセットされました。何も書かないと全部指定されるのでしょうか？分からず。。**

**【追記】：上記2点の疑問については、以下に追記をしました！**


# 無視について

git管理したくないものは、.gitignoreファイルにファイル名やファイルパターンを書いて置けばよい。

だけど例えば、「間違って管理したくないpiyo.txtをaddしちゃった。」という場合。

```zsh
git reset HEAD -- piyo.txt
```

として、インデックスから取り消せば良い。

さらには、「間違ってcommitしちゃった。」という場合。

```zsh
git rm --cached piyo.txt
```

として、piyo.txtをインデックスから削除しておけば、今後は無視される。


## 無視されるファイルを調べる

そもそも、ちゃんと無視されるべきファイルを知る方法。っていうのを知っておきたいです。

```zsh
# キャッシュされているファイルを表示。-cは省略可能。
git ls-files -c

# ソレ以外を表示。
git ls-files -o

# キャッシュされてるけど、.gitignoreに該当するもの。
git ls-files -i --exclude-standard
```
（キャッシュされてるっていうのは、つまりGitで管理されてるって意味ですかね。）

**`--exclude-standard`に対する理解、かなり怪しいです…`--exclude-<pattern>`の挙動とかよくわかりません。。**

**【追記】：こちらコメントにて、とても分かりやすく教えて頂いております。**


# git diff 差分について

初心者はとりあえず、びびってます。何がどうなって、どうなっているのか、よくわかんないです。`git diff`で色々チェックすれば挙動がわかります。ま、そもそも`git diff`がよくわかんないですけどね。

* ワーキングツリーとインデックスの差分
* ワーキングツリーとコミットの差分
* インデックスとコミットの差分

とかを知っていれば、いろいろ幸せになれそう。

```zsh
# ワーキングツリーとインデックスの差分
git diff

# ワーキングツリーとコミットの差分（<commit>はハッシュ値を入れれば良い）
git diff HEAD
git diff <commit>

# インデックスとコミットの差分(--cachedの後に何もなければHEADとの差分）
git diff --cached
git diff --cached <commit>

# コミットとコミットの違い。
gid diff <commit> <commit>
```



# git stash について

これは、**ワーキングツリーとインデックスの状態を、**作業中のブランチのWIP(Work In Progress)に保存してくれる。というコマンド。



# checkoutの意味を理解するのに時間がかかりました。

* だいたい3パターンくらいに分けると分かりやすいかと思っています。
* 基本的にはローカルリポジトリのある状態を、ワーキングツリーとインデックスに持ってくるイメージです。

### git checkout \<branch>

一番よくつかわれるのではないでしょうか。ブランチを切り替えます。このとき、\<branch>のHEADの状態を、インデックスとワーキングツリーに持ってきます。以上。

### git checkout

```zsh
git checkout <file>
```
でも良いかもしれません。

インデックス（のファイル）の状態を、ワーキングツリーに持ってきます。以上です。

### 問題はこれです。git checkout \<commit>



これを理解するのに、時間がかかりました。
（\<commit>はハッシュ値で置き換えてください。）
（`git checkout <commit> <file>`も同じパターンなので、特に詳細は書きません。）



コミットを

```zsh:master
A - B - C - D
            |
            HEAD
```

と順番に行ったとして、今Dです。この状態で、

```zsh
git commit HEAD^^
```

とするとどうなるか？

インデックスとワーキングツリーは、コミットBの状態になります。

**ではこのとき、ブランチはどうなるか？**

なんかmasterじゃなくて、Bに紐づく「detached from *****」みたいのになります。

は？なにこれ？**detachedってなに？detached HEADって何？**ってなります。

```zsh:master
            HEAD
            |
A - B - C - D
    |       
  detached HEAD
```

みたいになってるらしいです。
そして、この状態でごにょごにょいじって（コミットとかして）、たとえばマスターに戻ろうとすると、エラーになって、新しいブランチつくりなよ。と言われます。

ここでアドバイス通りに、新しいブランチをつくらないで、マスターなんかに戻ると、もうごにょごにょいじったところには戻れません。（detached（孤立した）だからね。）

というわけで、だいたいアドバイス通りにnew-branchを作成します。

```zsh:
A - B - C - D
    \
     E (new-branch)
```

結局こうなります。そしてめでたしです。


# 追記：改めて git reset について

前述の項目で少し謎が残っていました。First commit 前の状態で、addしたものをリセットするときに、
`git reset HEAD`ではダメで、`git reset HEAD -- .`などとした件です。

頂いたコメントをヒントにもう少し勉強してみたのですが、なんとなく分かった気がします。

## そもそも

First commmit 前の状態で`git reset HEAD`やるとどうなるか？

```zsh
% git reset HEAD
(git)-[master]
fatal: ambiguous argument 'HEAD': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
```

簡単に言えば、「HEADなんてないよ。」

で、「--使って、リヴィジョンとは繋がりの無いパスを指定していいよ。」

そう言われたので僕は、

```zsh
git reset HEAD -- .
```

などとしてみたのです。これでも上手く行きます。けど、そもそものマニュアルを見れば、

```zsh:man_git-reset
git reset [-q] [<tree-ish>] [--] <paths>...
This form resets the index entries for all <paths> to their state at <tree-ish>. (It does not affect the working tree, nor the current branch.)
```

こんな風なので、次のことを思いました。

* まずHEADそもそも無いし、あ、省略できるんだ。
* `--`も省略できるんだ。
* 「for all \<paths>」って書いてあるから、何も書かなかったら、全ファイル対象になるのかなぁ。

という感想を踏まえて、以下のコマンドで試しました。

```zsh
git reset
```

これで、addしたモノをリセットすることが可能でした。もちろん、

```zsh
git reset .
```

とパスを指定しても大丈夫です。

## まとめると

First commit 前の状態で、addしたモノをリセットしたいなら

```zsh
git reset [<paths>]
```

で良いです。多分HEADとか書いてるのは、変だと思います。勉強になりました。（これがそんなに多くの機会利用するコマンドだとは全く思いませんが！ただ、理解が深まり、幸せです。）


# git log --graph

ブランチをマージした後に、ブランチを削除しても、ちゃんとグラフには削除されたブランチの情報は残ります。


以上。

…引き続き。勉強したことを書くことがあるかと思います。