snippet: Git

## 特定のコミットのファイル内容を確認したい場合

```sh
git show コミット番号:ファイル名
```

## 過去のコミットをすべて変更したいとき

```sh:
git filter-branch -f --env-filter \
 "GIT_AUTHOR_NAME='user1'; \
  GIT_AUTHOR_EMAIL='user1@gmail.com'; \
  GIT_COMMITTER_NAME='user1'; \
  GIT_COMMITTER_EMAIL='user1@gmail.com';" \
 HEAD
```

## このリポジトリだけは別のアカウントでコミットしたい

* リポジトリに移動して以下実施

```bash:
git config user.name user1
git config user.email user1@gmail.com
# 設定確認
git config -l
```

## その他

```bash:直近のcommitを取り消す(ファイルの変更内容は消えない)
git reset --soft HEAD^
```

```bash:昨日のコミットを見たい
git log --since="1 days ago"
```

```bash:変更されたファイル名だけを表示してほしい
git log --name-status
git log --name-status --since="1 days ago"
```


```bash:指定のコミットを抽出したい
# ハッシュ値を指定
git show abcd1234:README.md > ~/README.md
```

## 全置換:コミットメッセージ

* [Gitで不適切なコミットメッセージを削除した公開リポジトリを作る - ククログ(2012-01-05)](http://www.clear-code.com/blog/2012/1/5.html)

```rb
git filter-branch --msg-filter 'sed -e "s@Merge.*internal.*\$@Merge@"' -f

git push -f
```

## リモートの内容にローカルを強制的に一致させたい

```rb:
git checkout ブランチ名
git fetch origin
git reset --hard origin/ブランチ名
```

## bashのプロンプトを変更

```bash:~/.bash_profile
parse_git_branch() {
     git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ (\1)/'
}
export PS1='[\u@\h \W\[\033[33m\]$(parse_git_branch)\[\033[00m\]]\$ '
```

ただし、`sudo -s`した後、`parse_git_branch()`が無いと言われるので注意。

## git log に 日付と author も表示する

```bash:~/.gitconfig
[alias]
g = log --graph --date=short --format=\"%C(yellow)%h%C(reset) %C(magenta)[%ad] %s %C(cyan)@%an%C(reset)\"
```

```bash:
git g
```

## パーミッションの変更を無視する

* [Git でファイルパーミッションの変更（chmod）を無視する - git config... « をぶろぐ](http://tetsuwo.tumblr.com/post/36066698390/git-chmod-git-config)

```
git config core.filemode false
```


## ブランチ作成しコミット、マージの流れ

```bash:branch作成し移る
git checkout -b docker-compose
(編集)
git commit
```

```bash:直前のコミットの取り消し(変更内容は保持
git reset --soft HEAD^
```

```bash:masterにマージ(--no-ffをつけたほうがツリーが見やすい)
git checkout master
git merge --no-ff feature-create-api
```

```bash:ブランチをpushする場合
git push origin docker-compose
```

```bash:マージ済みブランチを消す場合
git branch -d docker-compose
```

----

## 全ブランチをpush

```bash:
git push --all
git push --tags
```

```bash:.git/config
[remote "origin"]
        url = http://user1@mygitserver.com/user1/proj1.git
```

## git stash: 変更を一時的に退避

```bash:
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   index.html

Untracked files:
  (use "git add <file>..." to include in what will be committed)

	a

no changes added to commit (use "git add" and/or "git commit -a")
$ git status | diff
diff: missing operand after `diff'
diff: Try `diff --help' for more information.
$ git diff
$ git diff
diff --git a/index.html b/index.html
index d0686a7..1be90bc 100644
--- a/index.html
+++ b/index.html
@@ -3,4 +3,5 @@
 <li><a href="index_docker.html">docker</a>
 <li><a href="index_keepsrv.html">keepsrv</a>
 <li><a href="index_keepsrv_5min.html">keepsrv 5min</a>
+<li><a href="meishi.html">meishi</a>
 <li><a href="index_lifehack.html">lifehack</a>
$ git stash save
Saved working directory and index state WIP on master: 135763a 追記
HEAD is now at 135763a 追記
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Untracked files:
  (use "git add <file>..." to include in what will be committed)

	a

nothing added to commit but untracked files present (use "git add" to track)
$ git stash save
No local changes to save
$ git stash list
stash@{0}: WIP on master: 135763a 追記
$ git stash list -p
stash@{0}: WIP on master: 135763a 追記

diff --git a/index.html b/index.html
index d0686a7..1be90bc 100644
--- a/index.html
+++ b/index.html
@@ -3,4 +3,5 @@
 <li><a href="index_docker.html">docker</a>
 <li><a href="index_keepsrv.html">keepsrv</a>
 <li><a href="index_keepsrv_5min.html">keepsrv 5min</a>
+<li><a href="meishi.html">meishi</a>
 <li><a href="index_lifehack.html">lifehack</a>
$ git stash show stash@{0}
 index.html | 1 +
 1 file changed, 1 insertion(+)
$ git add a
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	new file:   a

$ git stash
Saved working directory and index state WIP on master: 135763a 追記
HEAD is now at 135763a 追記
$ git stash save
No local changes to save
$ rm a
rm: a: No such file or directory
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working directory clean
$ tig
$ git stash list
stash@{0}: WIP on master: 135763a 追記
stash@{1}: WIP on master: 135763a 追記
$ git stash show stash@{1}
 index.html | 1 +
 1 file changed, 1 insertion(+)
$ git stash show stash@{0}
 a | 1 +
 1 file changed, 1 insertion(+)
$ git stash drop stash@{0}
Dropped stash@{0} (d242b2ac3a2dd320461525c7a729a5fe93b82ad0)
$ git stash pop
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   index.html

no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (d53c44813188ec209824e054e4142c29d1261c1e)
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   index.html

no changes added to commit (use "git add" and/or "git commit -a")
```

## gitでリビジョンを行ったり来たり

* [gitでリビジョンを行ったり来たり - おもしろWEBサービス開発日記](http://d.hatena.ne.jp/willnet/20090904/1252081372)

> 例えばgitを使って一つ前のバージョンに戻して、しばらくして元のバージョンに戻したい時は
> git logでHEADのハッシュ値を控えておく
> git checkout HEAD^で一つ前のバージョンに戻す
> git checkout xxxxxxxx(控えておいたハッシュ値)で元に戻す

```bash:特定のコミット状態に戻す
git checkout ハッシュ値
もしくは
git checkout ハッシュ値 ファイル名
```

```bash:HEADに戻す
git checkout master
もしくは
git checkout master ファイル名
```

## gitをzshで使う際の注意

* zshでgit log HEAD^が効かない場合
  * git log HEAD~を使う。

## GitHubにpushする時、ユーザ名、パスワードの入力を求められる件対策

```diff:./.git/config
- url = https://github.com/tukiyo/dotinstall.git
+ url = git@github.com:tukiyo/dotinstall.git
```

![Screenshot from 2015-07-30 06:08:52.png](https://qiita-image-store.s3.amazonaws.com/0/25728/a7c10aa7-f8da-1c42-505f-f98b53f3351e.png)

* SSH のリンクをクリックしてからcloneすればよい。


## hookのメモ

```
chmod +x .git/hooks/pre-commit
```

```bash:.git/hooks/pre-commit
#!/bin/sh
make
```

```bash:.git/hooks/post-commit
#!/bin/sh
git push
```

## 基本操作

* git pull
  * remoteリポジトリからpullする


## commit関連

* git commit --amend
  * 直近のcommitをやり直す (コミットし忘れたものを追加するのに便利)

## branch操作

* git branch
  * branch一覧を表示

* git branch lesson/sandbox
  * branchを作成

* git checkout lesson/sandbox
  * lesson/sandbox ブランチに移動

* git checkout master
  * master ブランチに移動

* git cherry-pick <COMMITID>

## その他

* git log --oneline --decorate --graph
  * 1コミット1行で表示

* git reset --hard HEAD~
  * 直前のコミットを変更内容も含めて削除


## 文字化け対策

```bash:~/.gitconfig
[core]
	pager = nkf -w
```

## git diffの色付け

```bash:~/.gitconfig
[color]
	ui = true
```

# ブランチ

## リモートにブランチ追加

`git push origin ブランチ名`で作成できる。

```bash:
git branch devel
git checkout devel
git add -A
git commit -m "tes1"

git push origin devel
```

## ブランチを指定してclone

```bash:
git clone -b ブランチ名 https://github.com/tukiyo/setup_centos7.git
```

```bash:リモートのブランチ一覧
git branch --remotes
```

```bash:ブランチ間の差分表示
git diff master 先ブランチ名
git diff master 先ブランチ名 main.yml
git diff master 元ブランチ名 先ブランチ名 main.yml
```