Git備忘録

  1. コミットとプッシュ
    1. ステージングにadd
    2. コミット
    3. プッシュ
  2. プル
  3. 修正内容の確認
    1. 誰がいつどのコミットで修正したか調べる
    2. git status: ローカルとステージングの状況を確認
    3. git diff: 差分を調べる
      1. ローカルと直前のコミット(HEAD)との差分を確認する
      2. リモートとの差分を確認する
      3. git diff のバリエーション
      4. git diff と git statusの違い
    4. git log: コミット履歴の確認
      1. 頻出コマンド例
  4. 修正を元に戻す
  5. ブランチ
    1. ローカルブランチの確認
      1. -rオプション
      2. -vvオプション
      3. -aオプション
    2. ブランチを切り替え
    3. ブランチを作成
      1. リモートのタグからブランチを作成
      2. checkoutからswitch / restore への移行
      3. ブランチの命名規則
    4. アップストリーム
      1. アップストリームの指定方法
      2. git branch –set-upstream-to=origin/リモートブランチ名
      3. アップストリームの確認方法
    5. ブランチの更新
    6. ブランチ名変更
    7. ブランチ削除
      1. not fully mergedエラー
  6. マージ
    1. コンフリクトの解消
  7. スタッシュ
    1. 変更を保存
    2. スタッシュ一覧を確認
    3. 変更を適用
    4. スタッシュを削除
  8. 設定
    1. 必ずやるgitの初期設定
  9. Appendix
    1. CurrentとIncoming
    2. コミットせずにブランチを切り換えたい
    3. ローカルリポジトリとリモートリポジトリ
    4. マージリクエストとプルリクエストの違い
  10. インシデント
    1. 修正コミットが見つからない
      1. マージコミットの修正内容を確認するには?
    2. git diff に反映されない

コミットとプッシュ

ステージングにadd

git add -A  //すべてのdiffをadd
git add .  //カレントディレクトリ配下のdiffをadd

コミット

git commit -m "commit message"

プッシュ

git push origin master

ローカルと同名のリモートがあればそこへプッシュされる。無ければ新規ブランチがリモートに作成される。

このため、ローカルブランチの命名規則を、それとわかるように作成しておくことで、リモートに直接プッシュされるリスクを防ぐことができる。一般的には、feature/branch-name のように命名する。

プル

git pull origin branchName

修正内容の確認

誰がいつどのコミットで修正したか調べる

git blame [filepath]

修正者、修正日、修正コミットIDを表示してくれる、死ぬほど便利なコマンド。

git gui blame [filepath]

とすると、専用のウィンドウが開き、UIで詳細を確認できる。

git status: ローカルとステージングの状況を確認

ローカルの変更と、ステージングに上がっている変更を確認する。

git status

ファイル単位のソースコード差分を見ることはできない。

git diff: 差分を調べる

ローカルと直前のコミット(HEAD)との差分を確認する

git  diff

リモートとの差分を確認する

リモートとの差分を確認する場合は、git fetch でリモートの情報を最新化してから実行する。

git fetch
git diff --name-status origin/branchName

--name-status:ファイル名と編集タイプ(新規/編集/削除)を表示する。ファイル名のみで良い場合は--name-only

これを付けないと各ファイルの中身まで出力されるので、基本つける。

編集タイプの種類は以下。

  • A:新規追加ファイル(現在のブランチに新たに存在しているファイル)
  • D:削除ファイル
  • M:変更(修正)ファイル
  • R:リネーム(ファイル名変更)
  • C:コビー

特定の編集タイプのみ表示したい場合は以下。(Mのみ表示する例)

git diff --name-status origin/master | findStr "^M"

git diff のバリエーション

  • ローカルとリモートのDiff:git diff
  • ステージングとリモートのDiff:git diff --cached
  • リモート同士のブランチ比較:git diff origin/master origin/branchName
  • リモート同士のタグ比較:git diff origin/tag1 origin/tag2
  • ファイル単体のDiff:git diff -- [filePath]

git diff と git statusの違い

  • git status:ローカルとステージング、つまりは自身のPC内での変更を確認する
  • git diff:自身のPCとリモートの変更を確認する

git log: コミット履歴の確認

抑えておくべきオプション

--oneline:コミットを1行で表示(コミットID + メッセージ)
--graph:ブランチの分岐・マージをASCIIアートで表示
--decorate:ブランチ名・タグ名・HEADを表示
--all:全ブランチの履歴を表示(master以外も対象)
-m:マージコミットの差分も表示
--stat:修正ファイル名と変更行数を表示
-p:修正内容(パッチ)を表示

git log は現在チェックアウトしているローカルブランチのコミット履歴を表示する。

リモートの master ブランチの履歴を表示したい場合は以下。

git fetch origin
git log origin/master --oneline

頻出コマンド例

■全ブランチのマージ状況を確認する

git log --oneline --graph --decorate --all

■リモート master の特定ファイルのコミット履歴を確認する。

git log origin/master --graph --oneline [file path]

修正を元に戻す

git restore .

ファイルを指定して実行することも可能

git restore src/main/resources/db/**/*.sql

ブランチ

ローカルブランチの確認

git branch

-rオプション

リモートにあるブランチの一覧を表示する

-vvオプション

-vvオプションを指定すると、どのリモートブランチと紐づいているかも合わせて確認できる。

リモートと同期されているブランチは [origin/xxx] といった形式で表示される。

ただし、新規ブランチとして checkout したばかりで、push 先(upstream)が指定されていない場合は、checkout時に指定したリモートブランチが表示される。このとき、upstream自体はまだ設定されていない。

-aオプション

ローカルとリモート、すべてのブランチを表示する。

ブランチを切り替え

git switch branchName

ブランチを作成

ブランチを切り替えるときのコマンドに『-b』を付けることで、指定したブランチ名が無ければ新規作成される。

git fetch origin
git switch -c feature/branch-name origin/remote-branch
git switch -c <新ローカルブランチ名> origin/<リモートブランチ名>

リモートのタグからブランチを作成

リモートからタグ一覧を取得

git fetch --tags

ローカルのタグ一覧を確認

git tag

タグからブランチを作成

git switch -c [branch_name] [tag_name]

※タグに直接チェックアウトするのは危険

git switch [tag_name]

とするとチェックアウト自体は可能だが、HEAD が分離(detached HEAD)状態になるため推奨しない。

checkoutからswitch / restore への移行

ブランチを作成/切り替えする際、従来は git checkout -b を使用していたが、現在の Git では git switch の使用が推奨されている。

checkout はファイル復元にも使用されるため、用途が混在し、誤操作の原因となっていた。

そのため、以下のように使い分けるのが現在の推奨方法となっている。

  • ブランチの切り替え/作成:git switch
  • ファイルの復元:git restore

ブランチの命名規則

ブランチは、いつ作成されたのか、どのリモートを参照したのかといった情報を保持していない。

そのため、ブランチ名にそれらの情報を含めることは、しばしば実用的な運用となる。

命名規則を考える前に、ブランチ名に関するリスクを把握しておく。

checkout は、リモートブランチに対しても実行できる。例えば以下のコマンドでは、直接リモートにチェックアウトしてしまう。

git checkout origin/branch-name

detached HEAD となり、commit が保存されなかったり、リモートに直接プッシュしてしまう危険がある。

また、以下のようにリモートのブランチ名をそのままローカルで使用することも危険。

git checkout -b new-feature origin/new-feature

プッシュする際、修正中のローカルブランチと同名のリモートブランチが存在すると、そこに直接プッシュしてしまう。

リモートに同名のブランチが存在しなければ、新規ブランチとして作成されるだけで済む。

ブランチの命名に当たり、考慮したい点は以下

  • ベースとなるブランチにプッシュする前提の場合は同名でも良いが、異なるブランチとして使用する場合はブランチ名を変更する
  • リリース日や機能単位の情報をブランチ名に含める(新規開発なら機能単位、保守ならリリース日情報を含めるとよさそう)

まとめると

新規開発の場合の命名例

git checkout -b feature/func-name origin/my-app

保守開発の場合の命名例

git checkout -b feature/yyyymmddbase_yyyymmddrelease origin/yyyymmddrelease

断面はGitのログで追う、とするのであれば以下。シンプルが良ければ”release”も付けなくてよい。

git checkout -b feature/yyyymmddrelease origin/yyyymmddrelease

アップストリーム

アップストリームとは、ローカルブランチがどのリモートブランチと紐づいているのかを明示的に設定するもの。

あまり使われているのを聞いたことがないが、長期的に使用するブランチであれば、プッシュの間違いを防ぐ観点からも、設定しておくとよい。

アップストリームの指定方法

git branch –set-upstream-to=origin/リモートブランチ名

アップストリームの確認方法

git diff "@{u}"

ブランチの更新

リモートブランチの最新の状況を取り込む。

git fetch -p

gitは、一度でもプッシュしたことのあるリモートブランチは、削除されても指定先として残る(git branch -rをすると残っている)。

‐pオプションを付与することで、リモート側に存在しないブランチは、ローカル側からも参照しなくなる。

ブランチ名変更

リネームしたいブランチにチェックアウトしてから以下コマンド

git branch -m newBranchName

ブランチ削除

git branch -d localBranchName

not fully mergedエラー

ローカルブランチを削除しようとするとエラーになる場合がある。

git branch -d xxx
error: The branch 'xxx' is not fully merged.

このブランチは、まだどこにもマージしていない(修正内容は失われる)が、本当に削除しても大丈夫か?という警告。

-d を -D に変更して再実行すれば、強制的に削除される。

マージ

git merge --no-commit [branch_name]

マージを実行すると、ソースコードが更新され、コミットまで実行される。

コミットしたくない場合は、上記のように--no-commitオプションを付与する。

コンフリクトの解消

プッシュした修正と、他の人がすでに加えた修正が衝突する(同じコードを修正した)場合は、コンフリクトが発生する。

Gitが、ソースコードにコンフリクトの証跡を残すので、どちらの修正を採用するのかを決めて改めてコミットすることで解消する。

CONFLICT (content): Merge conflict in file xxx

アナウンスの通りに、コンフリクトの発生したファイルを開く。

Git が追加した HEAD と Incoming の差分がファイル内に現れているので、正しい修正を取り込む。

  • current changes (HEAD):コピー先(現在いるブランチの修正)
  • incoming changes:コピー元(git merge で指定したブランチ)

修正したら、コミットする。

git add .
git commit -m "任意のメッセージ"

スタッシュ

プルしたりチェックアウトしたりする場合には、ローカルの変更を一度コミットする必要がある。

ただ、中途半端に修正しているタイミングで、コミットなんかしたくない。

そんなときは、ローカルの修正を一時退避できるスタッシュを使用する。

変更を保存

git stash
git stash save "comment"  // コメント付きで保存

スタッシュ一覧を確認

git stash list

変更を適用

git stash pop  // 直前のスタッシュを適用して削除
git stash apply stash@{1}  // 特定のスタッシュを適用(削除しない)。引数にスタッシュ番号を指定

スタッシュを削除

git stash apply stash@{1}  // 特定のスタッシュを削除。引数にスタッシュ番号を指定
git stash clear  // すべてのスタッシュを削除

設定

必ずやるgitの初期設定

改行コードを勝手に変換しないようにする

git config --global core.autocrlf false
git config --global core.safecrlf true

Appendix

CurrentとIncoming

VSCodeなどで資源をマージする際、コンフリクトが起こると自分の修正とリモートの修正のどちらを優先するか聞かれる。

このとき、Current (現在の変更)とIncoming (入力側の変更)と表示されるが、どちらがどちらかよくわからない。

Incomingはorigin、つまりリモート側の変更で、 Currentは自身、つまりローカルの変更。

コミットせずにブランチを切り換えたい

一時的な退避であればスタッシュで良いが、開発目的で複数ブランチのローカルでの変更を保持したい場合は、ワークツリーを使用する。

参考:コミットせずにブランチを切り替えたい

ローカルリポジトリとリモートリポジトリ

git push origin master

上記のコマンドを見たとき、originとかmasterとか、何をやっているのかよくわかっていない人はまずこの概念を理解する。

  • ローカルとリモートが対になっている
  • originはリモートリポジトリのデフォルトの名前
  • masterはデフォルトのブランチ名
  • gitで指示するのはリモートの場所、送信元は自分の今いるブランチとなる

上記から改めて最初のプッシュコマンドを文字にすると、『ローカルリポジトリ(自分のPC)の変更を、リモートリポジトリ(GithubとかGitLabとか)のmasterブランチにプッシュする』となる。

gitコマンドの送信元は自身のPCのカレントディレクトリとなるため、コマンドでは出てこない。gitコマンドでは、リモートの情報だけ入力するものと理解しておく。

masterは特別なもののように思えるが、ただのデフォルトのブランチ名。自分で作るブランチと特に変わりはないので、変な誤解をしないようにする。

originも同じくデフォルトのリモート名なので意識する必要はない。リモート名をorigin以外の名前で複数管理することは少ないので、おまじない程度に考えておけばよい。

タグから復元する

タグは、今のHistoryとは全然違う位置にいるので、もちろんPULLなんかはできない。

リモートにあるタグを指定して、ローカルの新しいブランチとして使用する。

git fetch –tags  // リモートのタグ一覧を取得
git checkout <tag名>  // タグを指定してチェックアウト

この断面で検証および新たに修正を加えて、masterにマージすれば、pullと同じような動きになる。(pullは、fetchとmergeをしているに過ぎない)

マージリクエストとプルリクエストの違い

基本的に同じもの。GitHubではプルリクエストと呼び、GitLabではマージリクエストと呼ぶ。

インシデント

修正コミットが見つからない

git blame やfファイルの履歴(History)で修正履歴を追えないことがある。これは Git のマージコミットの仕様によるものであることが多い。

Git ではマージリクエスト(プルリクエスト)を承認する際に、2つのコミットが生成されることがある。

例えば、feature ブランチを master ブランチにマージする際、以下、2種類の修正が考えられる。

  • もともと feature ブランチに加えていたコミット
  • featureブランチを master にマージした際に作成される「マージコミット」

マージコミットは、わかりやすい例ではコンフリクトが発生した場合が挙げられる。

コンフリクトを修正するのは、feature ブランチの修正者ではなく、マージ対応者であるため、もともとのコミットとは区別される。

コンフリクトでなくても、マージする際に追加の修正を加えた場合は同じ挙動となる。そしてこのマージコミットの修正内容は、ファイルのhistoryや git blame の履歴として残らない

コミットタイトルは児童的に Merge branch 'feature/xxx' into 'master' といった表記になる。

マージコミットの修正内容を確認するには?

git log にオプションを付与すると、マージコミットも含めた修正履歴を見ることができる。

git log --oneline --graph -m -p [file_path]

-m がマージコミットの内容も表示するオプション。-p は修正内容の詳細も表示するオプション。

もしくは、「明らかにここで修正されているはず」というマージリクエスト(MR)が見つかったら、その前後のコミット履歴から先ほどのコミットタイトルを探し、マージコミットを特定する。

git diff に反映されない

git diff で修正差分を見ようとしたときに、ローカルで追加したファイルが反映されない。

これは、git diff では追跡対象として認識されているファイルいか表示しないため。新規ファイルは追跡対象と認識されずにgit diff では表示されないことがある。

git add してステージングに上げればgit diffでも表示されるようになる。

ステージングに上げたくない場合は、git status で確認する。これで見ると、新規ファイルは『Untracked files』というくくりで、まだgitで追跡されていないことがわかる。

コメント

タイトルとURLをコピーしました