Git Basic

Git Basic #

実用的なコマンド #

頻繁に使うコマンド #

$ git branch -a
$ git checkout -b sample_branch_name
# Edit source code
$ git status
$ git add .
$ git commit -m "message"
$ git push origin sample_branch_name
git tag sample_tag_name
git tag -n
git push origin sample_tag_name

指定したフォーマットでコミット・ログを表示 #

$ git log --graph --date=iso --pretty=format:"[%ad] %h %an : %s"

特定の注釈を含むコミットを検索 #

$ git log --oneline --grep "<pattern>"

コミット間の変更ファイル一覧を表示 #

$ git diff --stat <Commit A> <Commit B>

ファイル名のみ表示する場合

$ git diff --stat --name-only <Commit A> <Commit B>

Git 設定 #

バージョンを確認 #

$ git --version

設定の一覧を表示 #

設定適用範囲

  • system: システム全体に適用
  • global: ユーザー単位で適用(ユーザーのホームディレクトリ直下の設定ファイルを参照)
  • local: Gitリポジトリ単位で適用(.git ディレクトリ直下の設定ファイルを参照)
$ git config --system --list
$ git config --global --list
$ git config --local --list

適用範囲を指定しない場合 --local と同様に Gitリポジトリ内の設定を表示

$ git config --list

Gitリポジトリの管理するディレクトリ外で以下を実行した場合 エラーが発生

$ git config --local --list
fatal: --local can only be used inside a git repository

--list オプションの短縮版

$ git config --system -l
$ git config --global -l
$ git config --local -l

設定ファイルを直接編集 #

$ git config --system --edit
$ git config --global --edit
$ git config --local --edit

--edit オプションの短縮版

$ git config --system -e
$ git config --global -e
$ git config --local -e

どの設定ファイルに記載された設定が適用されているか確認 #

$ git config --show-origin user.name
$ git config --show-origin user.email
$ git config --show-origin core.autocrlf

ユーザー名/メールアドレスを設定 #

  • –global オプションを付けないと、該当のリポジトリのみ有効な設定になる
$ git config --global user.name <username>
$ git config --global user.email <mailaddress>

出力をカラーリングするよう設定 #

$ git config --global color.ui auto

コマンドにエイリアスを設定 #

$ git config --global alias.<aliasname> <commandname>

不要なファイルを管理対象外 #

  • .gitignore に記載されたファイル名は、Gitの管理対象外
  • .gitignore ファイル自体をコミットしておくこと
$ echo <file name> >> .gitignore

空ディレクトリを管理対象 #

  • Gitでは空ディレクトリは管理対象外
  • 空ディレクトリを管理対象にする場合、任意のファイルを配置
  • 慣例的に .gitkeep というファイルを使用
$ cd <directory name>
$ touch .gitkeep

プロキシサーバを経由してhttp接続 #

$ git config --global http.proxy <プロキシサーバのアドレス>:<プロキシサーバのポート番号>
  • .gitconfig ファイルの http の項目に次の設定を直接追加することもできる
[http]
proxy = <プロキシサーバのアドレス>:<プロキシサーバのポート番号>

ユーザー認証の必要なプロキシサーバを経由してhttp接続 #

$ git config --global http.proxy http://<ユーザ名ー>:<パスワード>@<プロキシサーバのアドレス>:<プロキシサーバのポート番号>
  • .gitconfig ファイルの http の項目に次の設定を直接追加することもできる
[http]
proxy = http://<ユーザー名>:<パスワード>@<プロキシサーバのアドレス>:<プロキシサーバのポート番号>

基本操作 #

リポジトリを作成 #

$ git init

ファイルやディレクトリをインデックスに登録 #

$ git add .
$ git add *.txt

インデックスに追加されたファイルをコミット #

$ git commit

変更されたファイルの一覧を表示 #

$ git status

変更されたファイルの差分を表示 #

$ git diff

コミットログを表示 #

$ git log

コミットログを表示 #

git log コマンドで参照したコミットやHEADを指定

$ git show <commit>

ファイルやディレクトリ名の変更や移動 #

$ git mv <old file name> <new file name>

管理対象ではないファイルを削除 #

  • -n : 削除されるファイルを確認
  • -f : 実際にファイルを削除
  • -x : .gitignore に指定されたファイルも削除
$ git clean

手元で変更したインデックスに登録されていないファイルを元に戻す #

$ git checkout -- <file>

インデックスに登録したファイルの取り消し #

$ git reset HEAD -- <file>

以前にコミットしたことのあるファイルだけを全てインデックスに登録 #

$ git add -u

コミットログ操作 #

コミットログを表示 #

$ git log

各コミットログを1行で表示

$ git log --oneline

git log の主なオプション #

オプション内容
-n件数を指定して表示
–relative-date相対フォーマット (“3 days ago” など) で日付を表示
–oneline1行で表示
–prettyフォーマットを指定して表示. オプションは oneline, short, full, fuller, fomat(独自指定)
–graphブランチやマージの履歴をアスキーグラフで表示

git log --pretty のフォーマット #

置換文字列内容
%Hコミットのハッシュ
%hコミットのハッシュ (短縮版)
%Tツリーのハッシュ
%tツリーのハッシュ (短縮版)
%P親のハッシュ
%p親のハッシュ (短縮版)
%anAuthor の名前
%aeAuthor のメールアドレス
%adAuthor の日付 (-date= オプションに従った形式)
%arAuthor の相対日付
%cnCommitter の名前
%ceCommitter のメールアドレス
%cdCommitter の日付
%crCommitter の相対日付
%s件名

git log の日付フォーマット #

フォーマット内容
relative相対時間 (3 days ago)
localローカルタイムゾーン
isoISO 8601 フォーマット
rfcRFC 2822 フォーマット
shortYYYY-MM-DD
raw%s %z
default標準

直前のコミットの内容を修正 #

現在のブランチの先頭のコミットに上書き 入力画面が表示されるのでコミットログを確認して保存

$ git commit --amend

入力画面が表示されず即上書き保存

git commit --amend --no-edit

直前のコミットのコメントだけを修正 #

インデックスにファイルを登録していない状態で再コミット
入力画面が表示されるのでコメントを修正して保存

$ git commit --amend

過去のコミットの内容を修正 #

  1. 指定したコミットより後のコミットを指定すると、コミットの一覧が表示される
  2. その中から修正したいコミットを見つけてその行の pick の文字を edit に変更して保存・終了する
$ git rebase -i <commit>
  1. 修正したいファイルを編集、保存した後に --amend オプションを指定してコミット
$ git commit --amend
  1. --continue オプションを指定し rebase を実行
$ git rebase --continue

過去のコミットのコメントを修正 #

  1. 指定したコミットより後のコミットを指定すると、コミットの一覧が表示される
  2. その中から修正したいコミットを見つけてその行の pick の文字を edit に変更して保存・終了する
$ git rebase -i <commit>
  1. 修正したいファイルを編集、保存した後に --amend オプションを指定してコミット
  2. コメントの入力画面が表示されるので、コメントを修正
$ git commit --amend
  1. --continue オプションを指定し rebase を実行
$ git rebase --continue

rebase を途中で中止 #

$ git rebase --abort

HEADの移動履歴を表示 #

過去に HEAD が指していたコミットの一覧を表示(削除したコミットや rebase 等によってまとめられたコミットなども表示)

$ git reflog

ブランチの先頭の移動履歴 #

過去にそのブランチの先頭が指していたコミットの一覧

$ git reflog <branch name>

直前のコミットを取り消し #

$ git reset --hard HEAD~

rebase を取り消し #

  1. HEADの移動履歴から rebase 直前のコミットを確認
$ git reflog
  1. 見つけたハッシュ値を <commit> で指定して reset を実行
$ git reset --hard <commit>

直前の reset を取り消し #

reset 前のコミットは ORIG_HEAD という名前で参照できるので、これを指定して reset を実行

$ git reset --hard ORIG_HEAD

ブランチを間違えてしまったコミットを移動 #

<commit> で指定したコミットを現在のブランチにコピー

$ git cherry-pick "<commit>"

特定のコメントを含むコミットを検索 #

<pattern> で指定した文字がコミットログに含まれるコミット

$ git log --grep "<pattern>"

ブランチ操作 #

ローカル・ブランチの一覧を表示 #

$ git branch

特定の文字列を含むブランチをローカル・ブランチから検索 #

$ git branch --list 'sample-*'

or

$ git branch -l 'sample-*'

ローカル・ブランチとリモート・ブランチの一覧を表示 #

$ git branch --all

or

$ git branch -a

特定の文字列を含むブランチをローカル・ブランチとリモート・ブランチから検索 #

$ git branch --all --list 'sample-*'

or

$ git branch -a -l 'sample-*'

ブランチを作成 #

$ git branch <branch name>

ブランチ名を変更 #

$ git branch -m <old branch> <new branch>

ブランチを削除 #

$ git branch -d <branch name>

ブランチを強制的に削除 #

HEAD にマージされていないコミットがあるブランチを強制的に削除

$ git branch -D <branch name>

ブランチを切り替え #

$ git checkout <branch>

ブランチの作成と切り替えを一度に実行

$ git checkout -b <branch>

ブランチをマージ #

$ git merge <branch>

fast-forwardなマージであってもマージコミットを作成
ブランチが存在したという情報を残したいときに有用

$ git merge --no-ff <branch>

リモート操作 #

既存のリモートリポジトリを複製 #

$ git clone <repository url>

リモートリポジトリを追加 #

$ git remote add <name> <repository url>

リモートリポジトリの一覧を表示 #

$ git remote

リモートリポジトリのブランチからローカルリポジトリのブランチを作成 #

$ git checkout <branch>

リモートリポジトリにブランチを作成 / ブランチに変更内容を反映 #

  • repositoryrefspec は省略可
  • repository には remote add コマンドで追加したリポジトリ名以外にURLを直接指定可
  • repository を省略した場合, 追跡しているリモートリポジトリを指定
  • refspec はブランチ名などを指定可
  • refspec を省略した場合, デフォルトでは全てのブランチが対象
$ git push <repository> <refspec>

リモートリポジトリのブランチの変更内容を確認 #

  • リモートリポジトリでの変更内容を確認したいがローカルリポジトリには反映させたくない場合に fetchを実行
  • repositoryrefspec は省略可
  • repository には remote add コマンドで追加したリポジトリ名以外にURLを直接指定可
  • repository を省略した場合, 追跡しているリモートリポジトリを指定
  • refspec はブランチ名などを指定可
  • refspec を省略した場合, デフォルトでは全てのブランチが対象
$ git fetch <repository> <refspec>

リモートリポジトリから削除されたブランチをローカルリポジトリでも削除 #

$ git fetch --prune

or

$ git remote prune <repository>

リモートリポジトリのブランチの変更内容をローカルリポジトリのブランチに反映 #

  • pull = fetch + merge
  • repositoryrefspec は省略可
  • repository には remote add コマンドで追加したリポジトリ名以外にURLを直接指定可
  • repository を省略した場合, 追跡しているリモートリポジトリを指定
  • refspec はブランチ名などを指定可
  • refspec を省略した場合, デフォルトでは全てのブランチが対象
$ git pull <repository> <refspec>

リモートリポジトリのブランチを削除 #

$ git push --delete <repository> <branch name>

リモートリポジトリにタグを作成 #

$ git push <repository> <tag name>

リモートリポジトリのタグを削除 #

$ git push --delete <repository> <tag name>

登録済のリモートリポジトリのアドレスを変更 #

指定した名前で登録されているリモートリポジトリのアドレスを のアドレスに変更

$ git remote set-url <name> <newurl>

登録済のリモートリポジトリの名前を変更 #

$ git remote rename <old> <new>

サブモジュール(submodule)操作 #

サブモジュールの設定 #

.gitmodules というファイルを作成して以下の内容を記述

[submodule "<submodule name>"]
	path = <directory name>
	url = <repository url>

e.g.)

[submodule "themes/hugo-book"]
	path = themes/hugo-book
	url = https://github.com/alex-shpak/hugo-book

サブモジュールを含めて既存のリモートリポジトリを複製 #

$ git clone --recursive <repository url>

サブモジュールを後から複製 #

$ git submodule update --init --recursive

サブモジュールのリモートリポジトリのブランチを指定し最新を反映 #

$ git submodule add -b <branch name> <repository url>

サブモジュールのリモートリポジトリのマスタの最新を反映 #

git submodule update --remote

タグ操作 #

ローカルのタグの一覧を表示 #

タグ名のみ

$ git tag

タグ名と注釈

$ git tag -n
  • -n 表示する注釈の行数
$ git tag -n1

リモートのタグの一覧を表示 #

リモート・リポジトリ origin のタグの一覧を取得

$ git ls-remote --tags origin

リモートのタグを取得 fetch #

$ git fetch --all --tags

タグ付け (タグを作成) #

現在のコミットにタグ付け #

注釈なし

$ git tag <tag name>

注釈付き

$ git tag -m "<tag message>" <tag name>
$ git tag --message "<tag message>" <tag name>

注釈付き (viが起動)

$ git tag -a <tag name>
$ git tag --annotate <tag name>

後からコミットにタグ付け #

指定したコミット, 注釈付き

$ git tag -m "<tag message>" <tag name> <commit>
$ git tag --message "<tag message>" <tag name> <commit>

指定したコミット, 注釈付き (viが起動)

$ git tag -a <tag name> -m <tag message> <commit>
$ git tag --annotate <tag name> --message <tag message> <commit>

タグを削除 #

まだプッシュしていないタグは削除可

$ git tag -d <tag name>
$ git tag --delete <tag name>

タグを共有 #

リモート・リポジトリ origin にプッシュ

$ git push origin <tag name>

全てのタグをリモート・リポジトリ origin にプッシュ

$ git push origin --tags

タグをチェックアウト #

$ git checkout <tag name>

タグをチェックアウトすると同時にブランチを作成

$ git checkout <tag name> -b <branch name>

トラブル対応 #

Error “would clobber existing tag” #

リモートとローカルのリポジトリのタグ名が重複していることが原因
リモート・リポジトリのタグでローカル・リポジトリのタグを上書きし解消

$ git fetch --tags -f

過去のコミットの編集者(Author)とコミッター(Committer)を変更 #

編集者(Author)とコミッター(Committer)のユーザー名とメールを確認

$ git log --pretty=full
commit XXXXXXXXXX (HEAD -> sample-branch, origin/sample-branch)
Author: before-foo <before-foo@sample.com>
Commit: before-bar <before-bar@sample.com>

過去の全コミットを変更

 $ git filter-branch -f --env-filter \
     "GIT_AUTHOR_NAME='after-foo'; \
     GIT_AUTHOR_EMAIL='after-foo@sample.com'; \
     GIT_COMMITTER_NAME='after-bar'; \
     GIT_COMMITTER_EMAIL='after-bar@sample.com';" \
   HEAD

過去のコミットに反映されたことを確認

$ git log --pretty=full

リモートリポジトリへ強制的に反映

git push -f

特定の条件の過去のコミットのみ修正する場合

$ git filter-branch --commit-filter ' 
    if [ "$GIT_COMMITTER_EMAIL" = "before-bar@sample.com" ];
      then
        GIT_AUTHOR_NAME="after-foo";
        GIT_AUTHOR_EMAIL="after-foo@sample.com";
        GIT_COMMITTER_NAME="after-bar";
        GIT_COMMITTER_EMAIL="after-bar@sample.com";
        git commit-tree "$@";
    else
        git commit-tree "$@";
    fi'  HEAD

その他 #

特定のディレクトリやファイルのみチェックアウト #

mkdir work && cd $_
git init .
git sparse-checkout init --cone
git sparse-checkout set <target path of directory or file>
git sparse-checkout list
git remote add origin <remote url>
git pull origin <branch name>
ls -al <target path of directory or file>

HEAD~ と HEAD^ の違い #

  • ^ (キャレット): n番目の親
  • ~ (チルダ): 最初の親のみに続くn世代前の祖先

https://git-scm.com/docs/git-rev-parse#_specifying_revisions

G   H   I   J
 \ /     \ /
  D   E   F
   \  |  / \
    \ | /   |
     \|/    |
      B     C
       \   /
        \ /
         A
A =      = A^0
B = A^   = A^1     = A~1
C =      = A^2
D = A^^  = A^1^1   = A~2
E = B^2  = A^^2
F = B^3  = A^^3
G = A^^^ = A^1^1^1 = A~3
H = D^2  = B^^2    = A^^^2  = A~2^2
I = F^   = B^3^    = A^^3^
J = F^2  = B^3^2   = A^^3^2

バージョンアップ #

macOS #

$ git --version
$ brew ls | grep git
nothing
$ brew install git
$ brew link --overwrite git
$ which git
/usr/local/bin/git
$ ls -la /usr/local/bin/git
$ git --version

References #