Skip to content

Instantly share code, notes, and snippets.

@acevif
Last active May 15, 2024 12:20
Show Gist options
  • Save acevif/30a5d8c0177a04e4fd6b0765ee38d374 to your computer and use it in GitHub Desktop.
Save acevif/30a5d8c0177a04e4fd6b0765ee38d374 to your computer and use it in GitHub Desktop.
Git関連のメモ

Gitメモ

Gitチートシート

  • git diff foo..bar git diff foo bar - https://yakst.com/ja/posts/4116
  • git diff foo...bar - https://yakst.com/ja/posts/4116
  • git diff HEAD - HEADと現在のワークツリーの差を見る. git diff --cachedの差分とgit diffの差分を合わせた差分
  • git log foo..bar - https://yakst.com/ja/posts/4116
  • git 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-dif diffの場合と対象が違うので注意
  • 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 に書く
    • 自分の環境だけこのプロジェクトだけで無視するファイル (当該プロジェクトでしか使っておらず自分しか使ってないもの): .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) を有効にする。便利そうなので検証中。

方針

Gitの導入・教育

Gitを教えたり導入したりした経験から来る知見を書いておきたい。

  • Gitは難しい。しかしそれは、Gitが難しいからではなくファイル管理・バージョン管理が本質的に難しいからだ。
    • Gitは 無駄に 小難しいと思われている。Gitはコマンドが多いし、英語だし…
    • ファイル管理・バージョン管理は 難しくない と思われている。人々は今までもファイル管理・バージョン管理をやってきていて、その能力や理解に自信を持っている。間違いなく頻繁に事故が起きている(上書き等)が、事故に気づいていないし事故に気づくためのワークフローを整備していない。このギャップがファイル管理・バージョン管理と、Gitの習得を困難にしている。
  • わかってるはずの人も事故る。
  • push --forceは危険なのはよく知られている。しかし--force-with-leaseでも危険だ。わかってるはずの人も事故る。
    • こんな実体験がある: 私「developの履歴が汚過ぎるので巻き戻すためgit push --force-with-leaseしていいですか? まだpushされて間もないので」→リーダー「いいですよ」→古いdevelopブランチから生えたブランチがリーダーのローカルにあって、後で大変ややこしいことになった。全てのローカルリポジトリのdevelopとそこから派生したブランチを消し去ってからforce-with-leaseを行うくらいで丁度良い。わかってるはずの人も事故る。
  • 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がきちんと入力されていないケースに至っては更に多い。)
    • 著作権者が設計の決定者・責任者とは限らない。
    • 設計の決定の背景には、何か致し方ない事情があったかもしれない。

その他

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment