git diff foo..bar
git diff foo bar
- https://yakst.com/ja/posts/4116git diff foo...bar
- https://yakst.com/ja/posts/4116git diff HEAD
- HEADと現在のワークツリーの差を見る.git diff --cached
の差分とgit diff
の差分を合わせた差分git log foo..bar
- https://yakst.com/ja/posts/4116git log foo...bar
- https://yakst.com/ja/posts/4116 https://stackoverflow.com/questions/7251477/what-are-the-differences-between-double-dot-and-triple-dot-in-git-difdiff
の場合と対象が違うので注意git merge-base foo bar
共通祖先を見つけるやつgit ls-files
git管理下にあるファイルの一覧。(ただしカレントディレクトリ以下にあるもののみ)git check-ignore <pathname>
gitignoreの対象になってるか確認するgit check-ignore -v <pathname>
gitignoreの対象になってるかに加えて、どの設定によりgitignoreされているかを確認するgit check-ignore -v *(D)
カレントディレクトリにあるgitignore対象ファイル(ドットで始まるファイルを含む)を確認する。(zshのglob qualifier(D)
を使用している。bashでは動かない。cf. man zshexpn→FILENAME GENERATION→Glob Qualifiers)git log --graph --one-line --all
履歴のツリー構造を見る。 よく使ってる。git stash show 0 -p
一番最近積んだstashの中身を見るgit switch develop && git fetch -p && git branch --merged develop | egrep -v "(^\*|master|main|develop)" | xargs git branch -d
いろいろ掃除する。マージ済みブランチをごっそり削除git log -G"someregex"
git log -S"somestring"
git log --grep=someregex
HEAD~~
HEAD~2
HEADの親の親HEAD^2
HEADに親が2ついるときの2番目の親 cf. Pro Git - 7.1 Git のさまざまなツール - リビジョンの選択 - 家系の参照git show -m 123abcd
マージコミットとその両親との差分を見るgit show --first-parent 123abcd
git diff 123abcd^ 123abcd
マージコミットと1番目の親との差分を見る- gitignore関連
- チーム全員で無視するファイル (プロジェクトで必須のソフトが生成するもの) →
repository/.gitignore
に書く - 自分のマシン全体で無視するファイル (OS固有のファイルやお気に入りのエディタ固有のファイルなど) →
$HOME/.config/git/ignore
に書く- (
~/.gitignore_global
に書くのはお勧めしない cf. https://zenn.dev/qnighy/articles/1a756f2857dc20 )
- (
- 自分の環境だけこのプロジェクトだけで無視するファイル (当該プロジェクトでしか使っておらず自分しか使ってないもの):
.git/info/exclude
に書く .gitignore
は自動生成するのがいい。シェルスクリプトでcurlでgitignore.ioを呼び出し生成。
- チーム全員で無視するファイル (プロジェクトで必須のソフトが生成するもの) →
- 1行が単純だとdiffもmergeもしやすいため、コーディングスタイルも行が単純になるものがいい。
GIT_PAGER='' git diff --word-diff=color | grep "shellScript = " | sed 's/\\n/\n/g;s/\\"/\"/g;'
XcodeのRun Script Build Phaseのdiffを見やすくgit log --graph --all --oneline --pretty=format:'%C(yellow)%h%C(reset) %s %C(dim green)(%cd)%C(reset)' --date=human
いい感じかもしれないログ表示git log -p --follow somefile
⸺ ファイルの過去の差分をずっと(ファイル名の変更を乗り越えて追跡しつつ)表示する。単一ファイルしか使えない(かも)。git restore --staged -p
インデックスの一部だけをunstageしたいときインタラクティブに操作できて便利git add -p
が使える人向けgit restore --staged --worktree --patch
git restore -S -W -p
インデックスの一部だけをworking directoryからdiscardする. インタラクティブに操作できて便利. こちらもgit add -p
が使える人向けgit config --global rerere.enabled true
rerere (reuse recorded resolution) を有効にする。便利そうなので検証中。
方針
- 基本コマンドは書きません。基本コマンドは https://training.github.com/downloads/ja/github-git-cheat-sheet/ などを参照してください。
Gitを教えたり導入したりした経験から来る知見を書いておきたい。
- Gitは難しい。しかしそれは、Gitが難しいからではなくファイル管理・バージョン管理が本質的に難しいからだ。
- Gitは 無駄に 小難しいと思われている。Gitはコマンドが多いし、英語だし…
- ファイル管理・バージョン管理は 難しくない と思われている。人々は今までもファイル管理・バージョン管理をやってきていて、その能力や理解に自信を持っている。間違いなく頻繁に事故が起きている(上書き等)が、事故に気づいていないし事故に気づくためのワークフローを整備していない。このギャップがファイル管理・バージョン管理と、Gitの習得を困難にしている。
- わかってるはずの人も事故る。
push --force
は危険なのはよく知られている。しかし--force-with-lease
でも危険だ。わかってるはずの人も事故る。- こんな実体験がある: 私「developの履歴が汚過ぎるので巻き戻すため
git push --force-with-lease
していいですか? まだpushされて間もないので」→リーダー「いいですよ」→古いdevelopブランチから生えたブランチがリーダーのローカルにあって、後で大変ややこしいことになった。全てのローカルリポジトリのdevelopとそこから派生したブランチを消し去ってからforce-with-leaseを行うくらいで丁度良い。わかってるはずの人も事故る。
- こんな実体験がある: 私「developの履歴が汚過ぎるので巻き戻すため
- rebaseは初心者は実務では禁止でもいい。教えてもらう状況の人に教えるべき内容ではない。厚いサポートが必要になるがそこまで手が回るチームならGitの導入なんてとうに終わっているだろう。
- 暗黙のルール・マナーが多いがそれも結局教えないといけない。
- 頼むからコミットメッセージの2行目は空行にしてくれ。
- ブランチングモデルはGitflow(A successful Git branching model)がおすすめ。一見、面倒であるが、かえって面倒が少ない。GitHub Flowは初心者チームへの導入には向いてない(CI / 自動テストなどが整備されたモダンなワークフローが前提になっているし、審査やQAや手動デプロイのフェーズがないウェブ向きだ)。
- 教える人は
git reflog
に慣れておこう。誰かがトラブった時に救済しなければならない。 - GitとGitHubがごっちゃになっている人が結構いるが、それに驚いているうちはまだ若い。
- Gitの読み方はジットではない。ギットだ。だがお客さんが「ジット」と発音しているときに訂正する必要はないぞ。
- Gitの競争優位性は3ウェイマージと分厚いエコシステムだ。「なぜGit?」に自信を持って嘘なく答えるためにこれを理解しておくと良い。
- ブランチの先頭のコミットのテストが通ったからといって、ブランチをマージした後のコミットでもテストが通るとは限らないぞ。それらは全く別のコミットだ。
- Gitにおけるコンフリクトの解消は行志向の表面的なものでしかない。論理的なコンフリクト(=矛盾)は十分なテストによりはじめて認識できるものだ。
- git blameだけを根拠に反射的に人をblame(=責める=とがめる)してはならない。
- authorとして設定されている人が著作権者とは限らない (コードを移動しただけかもしれない。authorが誤っていることも多い。そもそもcommitのcommiterとauthorが別であることを知らない人も多く、authorがきちんと入力されていないケースに至っては更に多い。)
- 著作権者が設計の決定者・責任者とは限らない。
- 設計の決定の背景には、何か致し方ない事情があったかもしれない。
- ブランチ名
master
はBitKeeper由来で、slaveとの対比で使われていた https://piro.sakura.ne.jp/latest/blosxom/webtech/2020-06-12_migrate-default-branch-from-master-to-trunk.htm