Git備忘録

コミットとプッシュ

ステージングに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 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 branch

-rオプション

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

-vvオプション

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

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

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

-aオプション

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

ブランチを切り替え

git checkout branchName

ブランチを作成

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

git checkout -b feature/branch-name origin/remote-branch
git checkout -b [ローカルに作成するブランチ名] [origin/元にしたいリモートブランチ名]

ブランチの命名規則

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

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

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

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 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  // すべてのスタッシュを削除

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をしているに過ぎない)

インシデント

git diff に反映されない

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

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

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

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

コメント

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