ryota21silvaの技術ブログ

Funna(ふんな)の技術ブログ

これまで学んだ技術の備忘録。未来の自分が救われることを信じて

【初学者向け】Gitのコマンドの使い方をよく忘れるから、纏めてみた

はじめに

Git: もう怖くないGit!チーム開発で必要なGitを完全マスター 山浦 清透を受講した時のメモがあったので、今の知識をもとに整理してみました。 これから新しいコマンドの使い方を覚えた時には、この記事に纏めていこうと思います。


1. 基本コマンド

  • git init
    • ローカルリポジトリ(=.gitディレクトリのこと。gitに必要なものがほどんど入っている)の新規作成。
      ドット(.)は隠れフォルダを表している。
  • git clone URL
    • ローカルにリモートリポジトリのファイルをコピーする。
  • git add -A
    • 現在のディレクトリ配下の変更ファイルが、ステージング (Staging) という待機用リポジトリに置かれる。addしたファイルは本当にコミットの対象にすべきなのかgit statusgit diffとかで確認しておきたい。
  • git commit

    • 変更を記録する(=コミット)。ステージの内容をスナップショットとしてリポジトリに記録する(変更、新規作成、削除、複数ファイルの変更・作成・削除)。
  • git commit -m 'メッセージ'

  • git commit -v
    • エディターを立ち上げて、「どのファイルにどんな変更をしたのか」エディター上で確認できる。結構オススメ。
  • git status

    • 以下のような変更されたファイルを確認する。
      1. ワークツリーとステージの間で変更されたファイル(前回、ステージに追加してから変更したワークツリーのファイル)
      2. ステージとリポジトリの間で変更されたファイル(前回、コミットしてからステージに追加されたファイル)を確認できる。
  • git remote add origin URL名

  • git push -u origin master(ブランチ名)

    • ローカルリポジトリの内容をリモートリポジトリに送る(master=デフォルトのブランチ名)。
    • 最初に-uを付ければ、アップストリームブランチを指定してくれるので、次回からgit pushに省略可能。
    • featureブランチを切った時は、最初にgit pushとだけ実行し、アップストリームブランの指定を行うサジェスチョンを表示させるのが良い。

2. git diff系

  • git diff
    • git addする前の変更差分を確認する。ワークツリーとステージの間の変更差分を確認する。
  • git diff ファイル名
    • 特定のファイルの変更差分を見る。
  • git diff --staged
    • ステージしたけど、まだコミットしてない変更差分を見る。git addした後の変更内容を確認する。

3. git log系

  • git log
    • 今までの変更履歴(コミット)を確認する(最新のコミットから順に表示)。
  • git log --oneine
    • 変更履歴を1行で表示。
  • git log -p ファイル名
    • 指定したファイルの変更差分を表示する。
  • git log -n コミット数
    • 表示するコミット数を制限(最新順で表示)。よく使う。

4. git rm系

  • git rm ファイル名

    • ファイルの削除を記録する(削除された変更状態がステージに記録される)。
      これは、ファイルごと削除するということ(=コミットした記録だけではなく、ワークツリー内のファイルも削除)。ワークツリーからもローカルリポジトリからも削除したい時に使う。
  • git rm -r ディレクトリ名

  • git rm --cached ファイル名
    • コミットした記録は削除したいけど、ワークツリー内のファイルは残したい(ローカルリポジトリからだけ削除して、その変更状態がステージに記録される。
    • これらのコマンド実行後、lsでワークツリーのディレクトリ内を確認、git statusで変更されたファイルを確認をすれば、記録が分かる。

5. git mv系

  • git mv 旧ファイル 新ファイル
    • ファイルの移動(=ファイル名の変更)を記録する。つまり、ワークツリーのファイル名が変更されて、かつ、ステージにも変更が反映される。

6. ワークツリーのファイル内の変更を取り消したい

  • git checkout -- ディレクトリ名
  • git checkout --.
    • 全変更を取り消す。

7. addしたけど、その変更を取り消したい(=commit対象外にしたい)

更新内容自体は取り消さず、addしてインデックスに登録するのを取り消す。

  • git reset ファイル名
  • git resetだけだと、ステージングにあるファイル全てを取り消す。

8. git commitした後に、直前のコミットを取り消したい(git reset HEAD)

1. git logでコミット履歴を確認する。

$ gl -n 3                                                                                                                                                           【 feature/19_meal_record_crud_exception 】
commit 4419fad760dd4e703559660195577047d88f60c5 (HEAD -> feature/19_meal_record_crud_exception)
Author: ryota1116 <ryota@gmail.com>
Date:   Thu Aug 27 16:30:34 2020 +0900

    [Add]MealRecordの各ページを修正

commit 2d14341fb814920c1072bd0a1e09678ad43abcef (origin/feature/19_meal_record_crud_exception)
Author: ryota1116 <ryota@gmail.com>
Date:   Thu Aug 27 00:39:01 2020 +0900

    [Fix]MealRecord検索フォームのjsファイルを修正

commit 14e7eaaf4b36535e32b342b33b7e54120f11f9bb
Author: ryota1116 <ryota@gmail.com>
Date:   Thu Aug 27 00:17:06 2020 +0900

    [Add]MealRecordフォームのi18nを追記

2. 取り消したいcommitをrevertする。

  • git reset HEAD^で、HEADの1個前のコミットに戻る。git reset コミットIDでも可。
  • HEAD^^^で、HEADの3個前のコミットに戻る。
HEADの意味
  • HEAD -> aaa(ローカルブランチ名)が現在のブランチの場所を指定(記憶)しており、その指定されているブランチが最新のコミットの位置を記憶している。
  • origin/ブランチ名はリモートにpush済。

qiita.com

9. git pushした後に、直前のコミットを取り消したい(git revert)

  • git revert コミットID

revertするコミットを指定する感じ。
git logすると、commitとrevertのログが残ってるのが分かる。

  • ただし、revertしたコミットのファイルがローカルからも消えちゃう(前のコミットに戻ったから)ので、「revertしたコミットの変更」をrevertしてあげれば、変更内容をローカルに残せる。以下のように。

git revert <revertしたコミットID> -nで、revertしたコミットの変更を取り消す(直前のコミットIDの変更を削除したコミットを取り消す感じかね。

10. 直前のコミットを修正したい(=今のステージの状態をもとに、コミットの内容を上書きしたい)

  • git commit --amend
    • 例えば、ファイルの修正を忘れてた時に、ワークツリー内のファイルに変更を加え、git addgit commit --amendを行う感じ。

git commit --amendでaddし忘れたファイルを救済する - Qiita

注意点

  • リモートリポジトリにpushした後のコミットは絶対にamendで修正してはいけない!!!

    pushした後にそのコミットを修正したければ、git commitでもう一度新しいコミットを作って修正すること。

11. git remote系

リモートリポジトリの情報を確認する

  • git remote
    • 設定しているリモートリポジトリを一覧表示する
  • git remote -v
    • 設定しているリモートリポジトリのURLを一覧表示する。

リモートリポジトリを複数登録する

  • メリット

    • 複数のチームで作業するとき
    • 自分のリモートを持ちたいとき
  • コマンド

    • git remote add リモート名 リモートURL
      • リモート名(ショートカット)で、URLのリモートリポジトリを新規登録する。

12. git fetch系

  • リモートリポジトリから情報を取得する(フェッチ)

    • git fetch リモート名
    • git fetch origin
  • 特徴など

    • ローカルリポジトリに情報を保存するけど、ワークツリーには保存されない。
    • 具体的にはremotes/リモート/ブランチというリモートブランチに保存される。
      • git mergeでローカルリポジトリ(ローカルブランチ)に保存された情報を、ワークツリーに落とす。

13. git pull系

  • git pull リモート名 ブランチ名

  • リモートから情報を取得し、マージまでを一度にやりたい」ときに使う。

    • git fetchとgit mergeを同時に行っている

14. fetchとpull

  • fetchを使うのが基本オススメみたい。

    • pullは特殊な挙動を起こす。今自分がいるブランチに、pullしてきたブランチがマージされる。異なるブランチ同士が統合される恐れがある。ファイルがグチャグチャになる可能性があるということ。
  • 自分が「マスターブランチにいて、何の変更もしていないときに限って」、pullで情報を取得するなどを行うべき。

    • 安全なケースの時にだけpullを使うのが良さそう。

15. リモートの詳細情報を表示する

  • git remote show リモート名
    • fetchとpushのURL、リモートブランチ、git pullの挙動、git pushの挙動などが表示される。

16. リモート名を変更する、リモートを削除する

  • git remote rename 旧リモート名 新リモート名
  • git remote rm リモート名

17. ブランチとは

  • コミットを指すポインタのことで、並行して複数機能を開発するためにあるもの。
    • ブランチは分岐して開発するためにあるもので、他の人の行った開発が、自分の開発には影響されないメリットを持つ(複数の機能の共同開発が可能となる)。

18. HEADとは

  • 今自分が作業しているブランチを指し示したポインタのこと。
  • このブランチとHEADの2つ(リポジトリ内に保存されている)により、最新のコミットがどれか分かる(順にHEAD→ブランチ→コミットと指している)

19. branch関連のコマンド

ブランチの新規作成

  • git branch ブランチ名
    • ブランチを新規追加する。(ブランチの切り替えまでは行わない)

ブランチの表示

  • git branch
    • 今あるブランチの一覧を表示。
  • git branch -a
    • 全てのブランチを表示。リモートリポジトリも表示できる。

ブランチの切り替え

  • git checkout 既存ブランチ名
    • ブランチを切り替える。(HEADが指し示すブランチを切り替えるということ)
  • git checkout -b 新ブランチ名
    • ブランチを新規作成し、切り替えも行う。

ブランチ名を変更する

  • git branch -m 新ブランチ名
    • 自分が現在作業しているブランチの名前を変更する。

リモートにpushした後にブランチ名を変更する

git branch -m 新ブランチ名
git push origin :旧ブランチ名  # リモート上にある旧名のブランチを削除
git push origin 新ブランチ名

ブランチを削除する

  • git branch -d ブランチ名
    • masterにマージされていない変更が残っている場合、そのブランチは削除しないようになっている。安全。
  • git branch -D ブランチ名
    • 強制削除する。慎重に使うこと。

20. merge系

マージ・・・他の人の変更内容を自分のブランチに取り込む作業のこと。

  • git merge ブランチ名
    • 指定したブランチ名の変更内容を、自分が今いるブランチに取り込む。
  • git merge リモート名 ブランチ名
  • git merge origin master(リモートブランチ名)
    • origin(=GitHubのこと)のmasterブランチの内容を、自分の作業ブランチに取り込む。

21. コンフリクトとは

  • 複数人の人が、同じファイルの同じ行に対して、異なる編集を行った時に起こること。
    • マージしたら、コンフリクトしてるよと言われ、Autoマージが失敗する。コンフリクトしても、落ち着いてファイルの内容をきれいに書き換えればOK。

22. コンフリクトの事故が起きにくい運用ルール

  1. 複数人で同じファイルを変更しない。
  2. pullやmergeする前に変更中の状態を無くしておく(commitstash(変更中のファイルを一時保管するコマンド)で変更中のファイルを無くしておく)。
  3. pullするときは、pullするブランチに移動してからpullする(同じ名前のブランチに移動してからpullしろってこと)。

23. ブランチを利用した開発の流れ

  • masterブランチをリリース用ブランチとして使い、開発はトピックブランチを作成して進めるのが基本。
    • masterブランチを常に最新のリリース状態に保っているから、最新のリリース内容がどんなものかmasterを見れば分かるようになっている!
    • 何かバグが起きても、一つ前のマスターブランチのバージョンに戻せばいいだけ。
  • masterで開発すると、最新のリリース状態がわからなくなるし、前のバージョンに切り戻すのが難しくなる。
    • 開発するときは、最新のマスターからトピックごとにブランチを切って、そのトピックブランチで開発を行う。そして、開発が完了したらmasterにマージする。

24. プルリクエストとは

  • 自分の変更したコードをリポジトリに取り込んでもらえるよう依頼する機能。バグを発生させない、コードの質を保つために、コードレビューを行ってもらう。

25. rebaseで変更履歴を修正する

  • git rebase ブランチ名
    • 「ブランチの基点となるコミット」を別のコミットに移動する。コミットの履歴を一直線に綺麗に整えられる。

26. リベースとマージの違い

履歴が一直線なのか、枝分かれなのか

- rebase...作業の履歴を消したい場合

  • 履歴をきれいに保つことが可能
  • コンフリクトの解決が若干面倒(各コミットごとにコンフリクトが発生する)

- merge...作業の履歴を残したい場合

  • コンフリクトの解決が比較的簡単(コンフリクトが一度しか発生しない)
  • マージコミットがたくさんあると履歴が複雑化する

27. リベースとマージの使い分け

  • プッシュしていないローカルの変更には、リベースを使う
  • プッシュした後はマージを使う。コンフリクトしそうな時もマージを使う。

注意点

  • githubにプッシュしたコミットをリベースするのは絶対NG!!

    • git push -fは絶対NG

28. pullにはマージ型とリベース型がある

  • マージ型
    • マージコミットが残るから、マージしたという記録を残したいときに使う。
  • リベース型
    • マージコミットが残らないから、Githubの内容を取得したいだけのときは以下のコマンドを使う。
      • git pull --rebase リモート名 ブランチ名

29. 複数のコミットをやり直す(git rebase)

  • git rebase -i コミット名
  • git rebase -i HEAD~3
    • 直前3つのコミットをやり直す

30. Git管理対象外に置きたくないファイルをpushしてしまった時

秘匿情報の入ったファイル、アプリケーションとは関係のないスクショなどを.gitignoreの中に指定するのを忘れ、pushしちゃった時に、そのファイルをGit管理対象外にする。

git rm --cached ファイル名

このコマンドで対象にされたファイルは、.gitignoreが適用されるようになる。

git rm --cached ファイル名とすると、ローカルからファイルが一旦消えるため、どこかにバックアップを取っておく。
push→pullしたあと、ファイルがdeletedになるから、ローカルにコピーして書き直せばおk。

31. git pushrejectされた時の対処法

ローカルでコミットした後に、Githubへpushしようとすると以下のようなエラーが表示されることがある。

~/workspace/app/cat_meow_miaow
$ git push --set-upstream origin master 【 master 】
To https://github.com/ryota1116/cat_meow_miaow.git
 ! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs to 'https://github.com/ryota1116/cat_meow_miaow.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

これは自分がpushするまでの間に、他の人が同じブランチ(以下の例ではmasterブランチ)にpushしているなどリモートの内容が変更されている場合に表示されるエラー。解決方法としては、リモートの最新の内容をローカルに反映させてあげる必要がある。
git pull リモートブランチ名 作業ブランチ名としてあげればいいので、今回の例でいけば、git pull origin masterを実行する。

もしくは、git pull --rebase リモートブランチ名 作業ブランチ名としてあげると、remoteの変更をpullした上で、その後にローカル上の変更をマージしてくれるので、コッチのが手っ取り早くはある。

$ git pull --rebase origin master    【 master 】
From https://github.com/ryota1116/cat_meow_miaow
 * branch            master     -> FETCH_HEAD
First, rewinding head to replay your work on top of it...
warning: unable to rmdir 'sound': Directory not empty
Applying: [Add]キー入力で音声出力
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...

これでpushできるようになったはず。

その他Gitでよく使うコマンド

  • git stash
  • git stash -u
  • git stash apply
  • git stash pop
  • git reset -soft HEAD^
  • git reset -soft HEAD^^
  • git reset -soft HEAD2^
  • git reset -hard HEAD2^(危険)
  • git merge --abort