Git初心者のメモ

# リモートとの同期

## ローカルとリモートが同期されているかチェックする

`$ git status`

- 結果
    - 同期が取れている場合

     ```sh
      # On branch master
      nothing to commit (working directory clean)
     ```

    - 同期が取れていない場合

    ```sh
     # On branch master
     # Your branch is ahead of 'origin/master' by 1 commit.
     #
     nothing to commit (working directory clean)
    ```

ただし、ローカルにあるリモートレポジトリの情報と比較しているので、必ずしも最新の状況を表示してくれるわけではない。リモートレポジトリの最新の状況を知るには`git fetch`しなければならない。

参考：https://gist.github.com/yatemmma/6486028#8-git-status-のメッセージを読み解く


## GithubにあるGitレポジトリをローカルにクローンする

```shell
$ git clone https://github.com/account-name/repository-name.git <directory name>
```
ただし、最後のディレクトリ名の有無は任意。

参考：[GitHubにあるリポジトリをローカルにcloneする方法](http://qiita.com/masamitsu-konya/items/abb572337156e4d003cf)

## MasterブランチをUpstreamに追従する

ローカルでmasterブランチにチェックアウトし、Upstreamをプルする。さらに、originにプッシュする。

```shell
$ git checkout master
$ git pull upstream master
$ git push origin master
```

参考：[GitHubでFork/cloneしたリポジトリを本家リポジトリに追従する - Qiita](https://qiita.com/xtetsuji/items/555a1ef19ed21ee42873)




<br />

## .gitignoreの変更をローカル・リモートに反映したい

### 1.  `.gitignore`にファイル名を追加

```sh
$ vi .gitignore
*.swp
.xcuserstate # 追加
```


### 2.   キャッシュ削除

```sh
$ git rm --cached *.xcuserstate
```


### 3.  commitしてpush

```sh
$ git add .gitignore
$ git commit -m "add file to .gitignore"
$ git push origin master
```

## 【2ステップ】Gitコマンドでtab補完を有効にする
http://qiita.com/growsic/items/1fff6286061e0cd27d54

### Push

#### リモートレポジトリに変更を反映させる

`$ git push origin remote_branch_name`

#### リモートレポジトリに強制的に変更を反映させる

```shell
$ git push -f origin foo
$ git push --force origin foo
# ２つは同等
```

#### リモートレポジトリから変更を受け取る
`$ git pull origin remote_branch_name`
<br />


# 差分の無視

## Gitignore

### .DS_STOREを無視したい

gitignoreファイルに記述を追加
http://qiita.com/anqooqie/items/110957797b3d5280c44f

他にも色々と無視した方がいいファイルがある(※iOS開発に偏っています)
http://blog.ishkawa.org/2012/10/27/xcode-git/
https://www.gitignore.io/api/objective-c

## Gitignoreにも記載せず、ローカルにGitで監視しないファイルを置きたい

`.git/info/exclude`に監視から外したい対象を記載する。

例：Documentフォルダ以下のファイルを監視しないように設定する

```sh
echo Document >> .git/info/exclude
```

# ブランチ

### 既存のブランチに移る
`$ git checkout branch_name`

### 新しいブランチを作る
`$ git branch new_branch_name`
<br />

### ブランチを新しく作成して、作成したブランチに移る
`$ git checkout -b new_branch_name`
参考：http://www.backlog.jp/git-guide/stepup/stepup2_3.html

### ローカルのブランチを一覧して、今いるブランチを確認
`$ git branch`

### ローカルのブランチ名を変更したい

`git branch -m <古いブランチ名> <新しいブランチ名>` 

今開いているブランチをリネームする場合は、新しいブランチ名のみ指定すればOK。

`git branch -m <新しいブランチ名>`

### 強制的にチェックアウト

`$ git checkout --force branch_name`

### リモートリポジトリのブランチをローカルにチェックアウトする

`$ git branch local_new_branch_name origin/remote_branch_name`

[リモートのgitブランチをローカルにチェックアウトする - setoya-blog](https://www.setoya-blog.com/entry/2012/11/04/132746)

### ローカルのブランチに紐付いているリモートのブランチを切り替える

まず、ローカルのブランチとリモートのブランチの対応関係は、`$ git branch -vv`で調べる。

```bash
$ git branch -vv
* feature/preview-available 5e643d1 [origin/feature/preview-available] add preview
  master                    acb0c71 [origin/master] add xcode project
```

ローカルの`feature/preview-available`ブランチのプッシュ先を、`feature/foo`に切り替える。

```bash
$ git push -u origin feature/foo
# 中略
To https://example.com/user-name/sample.git
   cfc509b..5e643d1  feature/preview-available -> feature/foo
Branch 'feature/preview-available' set up to track remote branch 'feature/foo' from 'origin'.
```

### ブランチのマージ

`sample_branch`を作って、`master`ブランチにマージします。

```bash
$ git checkout -b sample_branch
$ git checkout master #マージする先のブランチに移っておく必要がある
$ git merge sample_branch
```

### ブランチの削除

#### ローカルのブランチを削除したい

`$ git branch -d <branchname>`

#### リモートのブランチを削除したい

ブランチ構成が以下のような状況を考える。

```sh
$ git branch -a
* master
  develop
  remotes/origin/HEAD -> origin/master
  remotes/origin/feature/glayLabel
  remotes/origin/master
```

リモートレポジトリのfeature/glayLabelブランチを削除したいとする。

```sh
$ git push origin :feature/glayLabel
```

参考：http://blog.koogawa.com/entry/2014/03/08/121751


## コミット

### 空のコミットをしたい

`$ git commit --allow-empty -m "commit message"`

参考： http://fukajun.org/25

### カレントディレクトリにある、untrackedなファイルをまとめてステージングしたい

`$ git add .`

### コミットメッセージを修正したい

直前のコミットのメッセージを編集する場合

`$ git commit --amend -m "new message"`

2つ以上前のコミットのメッセージを編集したい場合

[Gitのコミットメッセージを後から変更する方法をわかりやすく書いてみた | 株式会社グランフェアズ](https://www.granfairs.com/blog/staff/git-commit-fix)

## リセット

### 直前のコミットを取り消す
- `$ git reset --soft HEAD^` コミットのみ取り消し。変更はステージングされた状態で残っている。
- `$ git reset HEAD^` コミットとステージングが取り消されている。変更はステージングから降ろされている。
- `$ git reset --hard HEAD^`コミット、ステージング、変更そのものが取り消されて前コミットから何も変更されていない状態に戻る。

#### コミットIDからリセット

```sh
git reset 7e26b50
```

コミットとステージングが取り消される。

#### 補足
- `HEAD^` コミット１個戻る
- `HEAD^^`　コミット２個分戻る
- `HEAD^^^` コミット3個分戻る

### 特定のファイルだけステージから下げたい

`$ git reset HEAD file_name`

http://qiita.com/annyamonnya/items/d845597606fbabaabcad

## スタッシュ

### スタッシュしたい

`$ git stash save "メッセージ"`

### スタッシュ一覧を表示する
`$ git stash list`

### 最後にスタッシュした内容を復活させたい
`$ git stash pop`

### untracked なファイルもスタッシュしたい

```
git stash save -u "スタッシュメッセージ"
```

## ブランチ操作

### リモートのブランチを削除したい
ブランチ構成が以下のような状況を考える。

```bash
$ git branch -a
* master
  develop
  remotes/origin/HEAD -> origin/master
  remotes/origin/feature/glayLabel
  remotes/origin/master
```

リモートレポジトリのfeature/glayLabelブランチを削除したいとする。

```shell
$ git push origin :feature/glayLabel
```

参考：http://blog.koogawa.com/entry/2014/03/08/121751

### originの向いている先を調べる

```bash
$ git remote -v
origin	https://github.com/username/some_repository.git (fetch)
origin	https://github.com/username/some_repository.git (push)
```

### リベースする

https://git-scm.com/book/ja/v1/Git-のブランチ機能-リベース
http://powerful-code.com/blog/2012/11/merge-or-rebase/
http://www.backlog.jp/git-guide/stepup/stepup1_4.html

2つめのリンクでマージとリベースの違いが説明されている。：

```shell
$ git checkout master
$ git merge bugfix
```

マスターに移ってトピックブランチをマージ。

```sh
$ git checkout bugfix
$ git rebase master
```

トピックブランチに移ってマスターをリベース。次にマージする。

### 2つのブランチの差分を見る

```sh
$ git diff master origin/master
```

### 古いコミットからブランチを生やす
古いコミットIDを調べて、2つめの引数に与える。

```sh
git branch -l newBranchName c5c3db0d60389df8a4e2886943f2668c7fb37096
```

### 特定のコミットのみ取り込む（チェリーピック）

```sh
git cherry-pick c727bd6
# git cherry-pick (コミットID)
```

 `cherry-pick A..B`の形で連続して取り込む際は、AはBよりも古いコミットでなければならない。

http://www.backlog.jp/git-guide/stepup/stepup7_4.html
https://www.kaitoy.xyz/2015/12/28/git-merge/
http://stackoverflow.com/questions/1670970/how-to-cherry-pick-multiple-commits

## コミット履歴を見る

`git log`で現在いるブランチのコミット履歴を表示。
次の例では、`--oneline`オプションで１コミット１行表示にしている。

```sh
$ git log --oneline 
76ff646 TableViewに関するReadmeの記述を追加
2dd5f49 Update README.md
2ea1264 Update README.md
3b0adee Update README.md
f405811 Create README.md
ede1d02 Add SampleCode
15574a3 Initial Commit
```

特定のブランチのコミット履歴を見ることもできる

```sh
$ git log master --oneline
d2e5033 Initial Commit
$ git log origin/master --oneline
d2e5033 Initial Commit
```



## 変更をステージングから下ろす

```sh
$ git reset HEAD [ファイルパス]
```

## タグを打つ

### 注釈付きタグを追加する

```sh
$ git tag -am "comment" tag-name
```

### タグを追加する

```sh
$ git tag tagname
```

### タグの一覧を表示する

```sh
$ git tag
tag1
tag2

$ git tag -n
tag1           tag-comment1
tag2           tag-comment2
```

## 過去の状態を確認する

`master`ブランチの最新の状態から、過去のあるコミットの状態に一時的に戻し、確認したら`master`ブランチの最新の状態に戻す


```sh
$ git stash    #最新の状態を一旦スタッシュ（一時退避）
# 必要があれば、git logなどで戻りたいコミットのIDを調べる
$ git checkout <commit_id>  #IDで指定したコミットの状態に戻る
$ git show #狙った箇所に移ったか確認
$ git checkout -f master #masterブランチのHEADに移動
```

詳しくは、[アクティビティ: git によるバージョン管理 9. 一時的に過去のコミットに戻る](https://tmytokai.github.io/open-ed/activity/git/text02/page09.html)を参照のこと。

***

# 参考

https://gist.github.com/yatemmma/6486028#file-git-lesson1-md
http://www.backlog.jp/git-guide/intro/intro1_4.html