Gitアドバンスドチートシート


冒頭の画像が素晴らしくわかりやすかったので紹介してみます。
以下はMaxence Poutord( [dev.to](https://dev.to/maxpou) / [Twitter](https://twitter.com/_maxpou) / [GitHub](https://github.com/maxpou) / [Linkedin](https://www.linkedin.com/in/maxpou/) )による[Git: Cheat Sheet (advanced)](https://dev.to/maxpou/git-cheat-sheet-advanced-3a17)の日本語訳です。


# Git: Cheat Sheet (advanced)

Gitでわからないことがあったときのために、この小さなチートシートを作りました。
`git commit`や`git pull/push`といった本当に基本的なコマンドはあえてスルーしているのでご注意ください。
このチートシートは"advancedな"使い方を目的としています。

![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26088/a1c1418f-4549-f818-4190-5e236ae8cb6f.png)

## 🧭 Navigation - Go to the previous branch

ひとつ前にいたブランチに戻る。

```git
git checkout -
```

## 🔍 Get the history

コミット履歴を取得。

```git
# 1コミットを1行で表示
git log --oneline

# 全てのコミットメッセージを取得し、'homepage'を含むものだけ抽出
git log --all --grep='homepage'

# コミッターで検索
git log --author="Maxence"
```

## 🙈Ooops #1: I reseted an unwanted commit. How to rollback?

不要なコミットをしてしまった。ロールバックはどうすれば？

```git
# やったことを一覧表示
git reflog

# 目的のコミットまでリセットする。 下記例ではHEAD@{4}
git reset HEAD@{4}
# もしくは↓でもよい
git reset --hard <commit-sha1>
```

もっと詳しく知りたい場合は、[What's happens when you `git commit`](https://dev.to/maxpou/what-s-happens-when-you-git-commit-59n7)を参照してください。


## 🤦‍♀️Ooops #2: I mixed-up with my local repo. How to clean it?

ローカルリポジトリと混ざってしまった。戻すにはどうすれば？

```git
git fetch origin
git checkout master
git reset --hard origin/master
# masterがorigin/masterと同じになった
```

## 🕵🏻‍♂️Difference between my branch and master

masterとの差分を見たい。

```git
git diff master..my-branch
```

## ✔ Custom commits

```git
# 最終コミットメッセージを変更したい
git commit --amend -m "A better message"

# 最終コミットに変更を追加したい、メッセージはそのまま
git add . && git commit --amend --no-edit

# CIビルド等のために空コミットをしたい
git commit --allow-empty -m "chore: re-trigger build"
```


## ♻️ Squash commits

最新の3コミットをまとめたいとしましょう。

・ `git rebase -i HEAD~3`
・ 最初だけ"pick"のままとし、残りを"squash"(あるいは省略形の"s")に置き換える。
・ コミットメッセージを整理して":wq"などで保存する。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">How to squash commits <a href="https://t.co/pTqLV7YVX7">https://t.co/pTqLV7YVX7</a> <a href="https://twitter.com/YouTube?ref_src=twsrc%5Etfw">@YouTube</a>さんから</p>&mdash; <a href="https://twitter.com/rana_kualu/status/1207256574902685696?ref_src=twsrc%5Etfw">2019年12月18日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


## 🎯Fixup

コミット`fed14a4c`に何か追加したいとしましょう。

![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26088/77a7b3f6-477e-30b8-fdc2-1a67d49a779b.png)

```git
git add .

git commit --fixup HEAD~1

git rebase -i HEAD~3 --autosquash
# エディタを保存して終了する
```

## 🕹Execute command on each commit when rebasing

`commit`毎にコマンド実行したい。

大規模な機能の場合、ひとつのブランチに多くのコミットが連なることがあります。
そしてテストが失敗し、ギルティなコミットを特定しなければならなくなります。
その場合、`rebase --exec`でコミット毎にコマンドを実行することができます。

```git
# 最後の3コミット全てnpmコマンドが走る
git rebase HEAD~3 --exec "npm run test"
```

![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26088/753cac4b-e756-1ee1-42ad-c9d6ac4a353e.png)

## 🦋Stash

`git stash`と`git stash pop`だけが全てではありません。

```git
# 追跡ファイルを全て保存する
git stash save "your message"

# stashされているリストを表示
git stash list

# 適用して削除
git stash apply stash@{1}
git stash drop stash@{1}
# ↑を1コマンドで実行
git stash pop stash@{1}
```

## 🗑 Clean

```git
# リモートに存在しなくなったブランチを削除
git fetch -p

# "greenkeeper"が含まれるブランチを全削除
git fetch -p && git branch --remote | fgrep greenkeeper | sed 's/^.\{9\}//' | xargs git push origin --delete
```

## 🐙 GitHub = Git + Hub

私は`git`のラッパーとして[Hub](https://github.com/github/hub)を使っています。
`alias git='hub'`するとgitコマンドでhubが動作します。

```git
# ブラウザでリポジトリを開く
git browse
```

他のコマンドは[こちら](https://hub.github.com/hub.1.html)にあります。


## 🦄 Bonus: my favourite git aliases

おまけ：個人的gitエイリアス。

```git
alias g='git'
alias glog='git log --oneline --decorate --graph'
alias gst='git status'
alias gp='git push'
alias ga='git add'
alias gc='git commit -v'

# 🤘
alias yolo='git push --force'

# useful for daily stand-up
git-standup() {
    AUTHOR=${AUTHOR:="`git config user.name`"}

    since=yesterday
    if [[ $(date +%u) == 1 ]] ; then
        since="2 days ago"
```

あなたのお気に入りコマンドは何ですか？


お読みいただきありがとうございます。
お役に立てば幸いです。
気に入ったら❤か🦄をください。
また質問やコメントもどうぞ。

元記事は[maxpou.fr](https://www.maxpou.fr/git-cheat-sheet)に投稿されています。

# コメント欄

「とても参考になった。」「素晴らしい。」
「`git-standup`すき。」
「タイポするから`alias gti='git'`って入れてる。」
「同じようなmergeやrebaseで同じようなconflictが出るときに自動解決してくれる[git rerere](https://git-scm.com/book/ja/v2/Git-%E3%81%AE%E3%81%95%E3%81%BE%E3%81%96%E3%81%BE%E3%81%AA%E3%83%84%E3%83%BC%E3%83%AB-Rerere)は重宝してる。」
「`git save`は非推奨になったから`git push -m`使った方がいいよ。」「`git save`なんて使ってたっけ？」「ごめん略しすぎた。`git stash save`のかわりに`git stash push -m`を使ってってこと。」「おｋ完全に理解した。」
「この[git lg](https://gist.github.com/Vadorequest/9d1f86b19dff5e1f7946a2f6b15a97f3)が好み。」
「`git branch -f master dev_branch`ローカルのmasterを上書き。`git push remote +dev_branch:master`リモートのmasterを上書き。」
「こんなエイリアスを使ってる。`gwip`はあらゆる差分を全てcommitする、`gunwip`はそれを元に戻す。」

```
gunwip='git log -n 1 | grep -q -c "\-\-wip\-\-" && git reset HEAD~1'
gwip='git add -A; git rm $(git ls-files --deleted) 2> /dev/null; git commit --no-verify --no-gpg-sign -m "--wip-- [skip ci]"'
```

自分のaliasを公開している人が何人かいました。


# 感想

まじか`stash save`がdeprecateになってたのかよ。
と思ったが、よく考えたら普段から`save`は略してたからデフォルトで`push`になっていたようだ。

さてこの記事ですが、チートシートというよりは便利なコマンド集ってかんじですね。
覚えておくといざというときに役立ちそうです。

あとコメント欄のエイリアスは参考になります。
私は[git lga](https://blog.toshimaru.net/git-log-graph/)くらいしか使ってないですが。
あとコメントに載ってた[このエイリアス集](https://github.com/nicksp/dotfiles/blob/master/git/gitconfig)を見て、頭に`!`を入れるとシェルコマンドを呼べることを知った。


インストールが必要なので全環境で使えるとは限りませんが、[Hub](https://github.com/github/hub)もよさそうですね。
gitコマンド上書きまでしてしまうのはさすがにどうかと思いますが、GitHubをメインで使っているなら導入しておくと便利になることでしょう。