Git のコマンドを紹介した記事はすでにたくさんありますが、 Pro Git Documentation の学習内容や、しばしば使用するが忘れやすいオプションのコマンドを基本的なことから知っておくと便利なコマンドまで、メモがてら紹介します。(今だとChatGPTにやり方を聞けば、だいたい説明してくれるとは思いますが。。。)こちらは、随時更新していきます。
※ 英語のドキュメントで調べたものをそのまま記載してたりしますので適宜コメントが英語になっています。
Git のコマンドを学ぶ意味
昨今ではGit、SourceTree など Git クライアントや VSCode の拡張機能(Git Graph など)でわかりやすく表示してくれて、Git のコマンドを理解しなくても直感的に操作が可能な中でGit のコマンドを学ぶメリットは以下の3つを挙げておきます。
- Git クライアントでは細かい Git の低レベルのコマンドまで行うことができない。
- Git について検索するとほとんどが Git コマンドで解説されている。
- Git クライアントよりもファイルの一覧表示や、過去のコミットからの詳細の検索はコマンドのほうが早く正確。
逆に Git リポジトリの可視化だったり、変更箇所の確認は Git クライアント方が使いやすいので適材適所で使い分けを行えば良いと思います。
基本コマンド
Gitのことはじめ
Git のコマンドを調べるときに使用するヘルプ系のコマンドや、Git の動作や環境を設定するための config の設定です。
git help
# To display the git[1] man page
$ git help git
# Prints all the available commands on the standard output.
# git で利用可能なすべてのコマンド一覧を表示する
$ git help [-a|--all]
$ git help <command>
$ git help config
# Prints a list of the Git concept guides on the standard output.
# git の場面ごとの使い方などコンセプトを表示する
$ git help [-g|--guides]
$ git help <concept>
$ git help everyday
git config
git の設定先は、system,global,local の3つがあり、順に優先度が上がっていきますがそれぞれの設定がどのファイルに記載されているか「–show-origin」でわかります。
# git の設定がどのファイルに定義されているかを確認する
$ git config --list --show-origin
# Mac環境での使用例
$ git config --list --show-origin
file:/usr/local/etc/gitconfig credential.helper=osxkeychain
file:/Users/user-name/.gitconfig user.name=username
file:/Users/user-name/.gitconfig user.email=example@domain.com
file:/Users/user-name/.gitconfig http.sslverify=false
file:/Users/user-name/.gitconfig alias.graph=log --oneline --decorate --graph --all
file:.git/config core.repositoryformatversion=0
file:.git/config core.filemode=true
file:.git/config core.bare=false
file:.git/config core.logallrefupdates=true
file:.git/config core.ignorecase=true
Gitがない環境でgitを導入した場合ですが、user.name と user.email の設定がないとコミットすることができないので必ず設定します。
$ git config --global user.name "user name"
$ git config --global user.email example@domain.com
あまり使用する機会はないかもしれませんが、vi コマンドなどを使用してファイルを開かなくても、–edit オプションで対象の設定ファイルを開いて編集できます。
# -e --edit : Opens an editor to modify the specified config file
# 各configファイルを開いて編集します。
$ git config --local --edit
$ git config --global --edit
$ git config --system --edit
よく使用するコマンドでオプションが長い場合、エイリアスを作成しておくと便利です。
# 「log --oneline --decorate --graph --all」→「graph」でエイリアスを作成する。
$ git config --global alias.graph 'log --oneline --decorate --graph --all'
$ git graph
# 例: git status → git st に置き換える
$ git config --global alias.br branch
$ git config --global alias.st status
$ git config --global alias.sw switch
$ git config --global alias.ci commit
$ git config --global alias.co checkout
Git for Windows を使用している環境だと設定によっては Git が自動変換を行い、リポジトリの改行コードが混在する場合があるので注意します。サクラエディタを使用すれば、改行コードが文字として現れるので確認するのにオススメです。Excel など日本語を含むファイル名が数字コードで文字化けするときは、 core.quotepath の設定を行う。
# 自動変換を行わない
$ git config --local core.autocrlf false
$ git config --local core.quotepath false
参照: 気をつけて!Git for Windowsにおける改行コード
複数のプロジェクトで社内、社外のサーバーにgitリポジトリが置いてある場合は、一般的には以下のような設定にするとよさそうです。
- 社外サーバーに対して、–global でプロキシを設定する
- 社内サーバーに対して、各個別のリポジトリでプロキシを空で設定する
# グローバルでプロキシの設定を行う
$ git config --global http.proxy http://proxy.example.com:8080
# 各個別のリポジトリでプロキシを空で設定する
git config --local http.proxy
# プロキシの解除
git config --local --unset http.proxy
※ –global で設定したプロキシに対して、–local で上書きしようとする場合に、–unset で解除することはできません。(当然、設定していないものに関しては解除することができないからですね。)だから、上書きするために空で設定する必要があります。
git remote
origin は「that is the default name Git gives to the server you cloned from」で git リポジトリをクローンしたときに Git がそのサーバに対してデフォルトでつける名前です。
# リモート名の表示
$ git remote
origin
# Be a little more verbose and show remote url after name.
# リモートと名前と、その名前に対応するURLを書き込み用と読み取り用の2つ表示
$ git remote -v
origin https://github.com/user-name/example.git (fetch)
origin https://github.com/user-name/example.git (push)
現在の変更に対する作業
git add
基本的にには変更したファイルはすべてコミット対象にすると思いますので「git add .」ですべてステージングすると思います。複数変更あるファイルの中からコミット対象のファイルを選択する場合、コミット対象をhunk毎に選択する場合はインタラクティブに行うと便利です。 7.2 Git Tools – Interactive Staging に詳しく記載されています。
# 追跡対象のファイルと対象外のファイル両方ともすべてステージングする。
$ git add .
# 追跡対象のファイルのみすべてステージングする。
$ git add -u .
ステージングするファイルは 「git add file1 file2 …」のように選択もできますが、複数あるとfile名の選択が大変で、
# インタラクティブモードに入る
$ git add [-i | --interactive]
*** Commands ***
1: [s]tatus 2: [u]pdate 3: [r]evert 4: [a]dd untracked
5: [p]atch 6: [d]iff 7: [q]uit 8: [h]elp
What now>
# Interactively choose hunks of patch between the index and the work tree and add them to the index.
# ファイルの変更すべてではなく、hunk毎にコミット対象にするかどうかを選択する。
git add [-p | --patch]
git mv
# to rename a file in Git
# Git管理内のファイルのリネームを行う
$ git mv <old-name> <new-name>
$ git status
renamed: <old-name> -> <new-name>
# 以下の2つのコマンド、削除して追加するのと同じ動作です。
$ git rm <old-name>
$ git add <new-name>
git rm
単純にファイルを削除するだけでは、git の追跡対象外にはなりません。git rm を使用して、削除、追跡対象外にします。
# The next time you commit, the file will be gone and no longer tracked.
# working directory から削除し、追跡対象外にする
$ git rm <file>
git stash
stash コマンドは修正を一時的に退避しておくコマンドです。checkout や switch 、リモートからpull する前などに使用します。7.3 Git Tools – Stashing and Cleaning に詳しく記載されています。
# List the stash entries that you currently have.
# stash の一覧を表示する
$ git stash list
# Like pop, but do not remove the state from the stash list.
# stashを削除せず、stashを適用する
$ git stash apply
$ git stash apply stash@{0}
# Tries to reinstate not only the working tree’s changes, but also the index’s ones.
# 通常はインデックスの状態でstashを行ってもインデックスの状態に再適用されないが、--index オプションでインデックスの状態で再適用する。
$ git stash apply --index
# Remove a single stash entry from the list of stash entries.
# stash を削除する
$ git stash drop
$ git stash drop stash@{0}
# Remove a single stashed state from the stash list and apply it on top of the current working tree state
# pop = apply + drop
# stashの適用と削除を行う
$ git stash pop
# ファイルを指定してstashする
$ git stash push -- <file-name>
# indexにある状態をkeepしながらstashを行う
$ git stash --keep-index
# include untracked files in the stash being created.
$ git stash [-u | --include-untracked]
# hunk毎にstashするかどうか決める。(git add -pと同じ方式)
git stash [-p|--patch]
履歴と状態の調査
git log
git log のオプションは複数あるので、有用だと思ったオプションを一例で紹介します。
# 先頭の7バイトのコミットのハッシュ値をとコミットメッセージを1行で表示
git log --oneline
# 変更されたファイル名も表示
git log --name-only
# 指定したファイルの変更を含むコミットログを表示する(パスである、完全マッチであること)
# git log -- <path>
$ git log -- *fil-name.*
# Continue listing the history of a file beyond renames (works only for a single file).
# --follow オプションでファイルがリネームされた場合も表示できる
$ git log --follow -- <path>
# 使用例: 1行で window.py の変更を含むファイルをファイル名とともに表示する
$ git log --oneline --name-only -- window.py
f604eee (origin/main, origin/HEAD) 削除
window.py
cfa44c2 commit
window.py
4f963c3 practice_commit
window.py
# コミットメッセージ内に pattern を含んでいるコミットログを表示する
$ git log --grep=<pattern>
# パッチテキストに <regex> に一致する追加/削除された行が含まれるコミットを表示する
$ git log -G<regex>
# ファイル内の指定された文字列の出現数 (追加/削除など) が異なるコミットを表示する
# 相違点なので行の位置が移動した場合などは対象外、関数が最初に作られた場合などで使用
$ git log -S<string>
$ git log -Sfunction-name
git diff
ソースコードの具体的な差分に関しては VSCode などエディターの Source Control 機能を使用した方が見やすく、わかりやすいですが特定のコミット間のファイル名の一覧を表示する場合など、一覧をテキストで表示する場合はCLIの方がやりやすかったりします。
# コミット間の変更ファイル一覧を表示する (2つとも同じ)
$ git diff --stat --name-only <commitID>..<commitID>
$ git diff --stat --name-only <commitID> <commitID>
# 使用例 (@はHEADと同じです)
# 現在いるブランチの最新の2つのコミットの変更ファイル一覧を表示
$ git diff --stat --name-only @^^..@
「..」と「…」の違いもあります。Stack Overflow の Answer に記載の図表がわかりやすいです。
$ git diff A...B
$ git diff $(git merge-base A B) B
参照: What are the differences between double-dot “..” and triple-dot “…” in Git diff commit ranges?
ヒストリーの拡大、マーキング、調整
ブランチの種類について概要は以下の通りです。詳細については Pro Git の 3.5 Remote Branches を参照すると良いです。
リモートブランチ (remote branch) | リモート環境にあるブランチという概念 (リモート追跡ブランチを指す場合もある) |
ローカルブランチ (local branch) | 手元のローカル環境で確認できるブラン (git branch -a で表示されるブランチ) |
リモート追跡ブランチ (remote-tracking branch) | ローカルブランチの一種 リモートブランチの状態を保持する参照 git fetch すると更新されるブランチ origin/<branch> のこと |
追跡ブランチ (tracking branch) | ローカルブランチの一種 リモートブランチと直接のつながりを持つローカルブランチ リモート追跡ブランチからローカルブランチにチェックアウトするときに自動的に作成されるブランチ |
上流ブランチ (upstream branch) | 追跡ブランチが追跡するブランチ 引数なしで git pull したとき対象になるブランチ |
git branch
# Move/rename a branch, together with its config and reflog.
# ブランチ名を変更する
$ git branch -m [<oldbranch>] <newbranch>
# -r, --remotes :List or delete (if used with -d) the remote-tracking branches.
$ git branch -r
# -a, --all : List both remote-tracking branches and local branches.
$ git branch -a
# Combine with --list to match optional pattern(s).
# list only the branches that match the pattern(s).
# パターンにマッチしたブランチ名を表示する
$ git branch -a --list <*pattern*>
# Only list branches which contain the specified commit (HEAD if not specified).
# 特定のコミットを含むブランチのみを表示する
$ git branch --contains [<commit>]
# to see which branches are already merged into the branch you’re on
# 現在いるブランチにすでにマージされたブランチを表示する
$ git branch --merged
# マージされたブランチは-d、マージされてないブランチは-Dで削除する
git branch -d <branch>
# "試験用"と名のつく一意のマージされていないブランチを強制削除する
git branch -D $(git branch|grep "試験用")
# ローカルブランチが追跡する上流ブランチを表示する
$ git branch -vv
# 現在のブランチの上流ブランチを設定する
$ git branch --set-upstream-to=origin/<branch>
$ git branch -u origin/<branch>
git commit
$ git commit -m "コミットメッセージ"
# tracked ファイルで変更された、修正されたファイルをすべてステージングし、コミットする。
$ git commit -am "コミットメッセージ"
# 以下と同じです。
$ git ddd -u .
$ git commit -m "コミットメッセージ"
# 直近のコミットの修正(コミットの SHA-1 が変わるため注意)
$ git commit --amend
git push
# git push の省略なしから省略ありまで
$ git push <送信先リポジトリ> <送信元ブランチ>:<送信先ブランチ>
$ git push https://github.com/t-nagayoshi/hangman_gui.git master:master
$ git push origin master:master
$ git push origin master
$ git push
$ git remote -v
origin https://github.com/t-nagayoshi/hangman_gui.git (fetch)
origin https://github.com/t-nagayoshi/hangman_gui.git (push)
git rebase
git rebase コマンドで過去のコミットメッセージを書き換えることができます。7.6 Git Tools – Rewriting History に詳しく記載されています。
# 複数のコミットメッセージの変更
$ git rebase -i HEAD~3
git checkout
# 起点となるブランチから新規のブランチを作成して、switch する
$ git checkout -b <new-branch> [<start-point>]
# If -B is given, <new-branch> is created if it doesn't exist; otherwise, it is reset.
# ブランチが存在していなければ作成し、存在すればリセットする。
$ git checkout -B <new-branch> [<start-point>]
# 以下のコマンドと同じです。
$ git branch -f <branch> [<start-point>]
$ git checkout <branch>
git switch
Git version 2.23 から git checkout の代わりに git switch を使用できます。checkout が working directory を書き換えてしまうため、switch と restore に機能が分かれてできたコマンドです。
# Switch to an existing branch
# 既存ブランチへの切り替え
git switch <branch>
# Create a new branch and switch to it
# 新規ブランチ作成と移動
git switch -c <new-branch>
# Return to your previously checked out branch
# 直前にチェックアウトしたブランチに戻る
git switch -
# grepでブランチが一意に決まる場合は、以下のように移動できます
git switch $(git branch | grep "ブランチ名に含まれる文字列")
その他のニッチなコマンド群
Git管理下のファイルをコミット対象から無視する
コミット対象外にする場合は .gitignore に記載しますが、コミットの追跡対象になっている場合などGitの管理下にある場合は除外されません。Git管理下にあるファイルをコミット対象から除外するには、update-index のコマンドの「–assume-unchanged」「–skip-worktree」オプションを使用します。
それぞれ名前の通りですが以下の違いがあります。
–assume-unchanged は直訳で「変更していないものとして仮定する」だけなので、 merge や reset などで working tree に更新があれば、それまでの変更は破棄されます。
–skip-worktree は直訳で「working treeをスキップ」ので merge や reset でも working tree の状態は更新されず、それまでの変更が保持されます。
$ git update-index --[no-]assume-unchanged <file>
$ git update-index --[no-]skip-worktree <file>
# 除外対象になったファイルの確認
# 追跡中のファイルは「H」assume-unchanged 設定は「h」skip-worktree 設定は「S」
$ git ls-files -v
# 各対象ファイルのみ表示する
$ git ls-files -v | grep '^h'
$ git ls-files -v | grep '^S'
Git のファイル管理状態を調べる
以下のコマンドで、Gitが管理しているファイルなどを調べることができます。
# リポジトリ内の全ディレクトリを表示
$ git ls-tree -dr --name-only --full-name --full-tree HEAD
# カレントブランチにコミットされたすべての追跡状態のファイルの一覧を表示
$ git ls-tree -r --full-tree --name-only HEAD
# リポジトリのルートディレクトリの絶対パスを取得
$ git rev-parse --show-toplevel
参照: How can I make git show a list of the files that are being tracked?
カレントブランチの派生元ブランチを表示する
Git のブランチの構成状態によっては必ずしもうまくいかなかった場合がありますが、大半は以下のパイプラインで組み合わせたやり方でいけそうです。エイリアスとして登録するには、コマンドで行うとエスケープが大変なので直接定義ファイルを開いたほうが良いです。
$ git show-branch | grep '*' | grep -v "$(git rev-parse --abbrev-ref HEAD)" | head -1 | awk -F'[]~^[]' '{print $2}'
# エイリアスとして登録する("のみ\"でエスケープします)
$ git config --global -e
[alias]
showbased = !"git show-branch | grep '*' | grep -v \"$(git rev-parse --abbrev-ref HEAD)\" | head -1 | awk -F'[]~^[]' '{print $2}'"
# エイリアスで実行する
$ git showbased