🍷

mixiさんの新卒研修が公開されてたから自分用備忘録としてまとめた~Git~

2021/05/21に公開

[WIP]ミクシィの21新卒技術研修の資料と動画を公開します!
自分も21卒エンジニアなので、復習も兼ねてGitの動画を拝見しました
めちゃくちゃ勉強になった無料で見れてええんかコレ...

事前知識

【git】分かりやすく!mergeは「合流」、rebaseは「付け替え」!
Git で「追跡ブランチ」って言うのやめましょう👈参考させていただいた記事

  • ワークツリー・・・実際に作業をしているディレクトリ
  • インデックス・・・ステージング先、.git/index
  • (ローカル)リポジトリ・・・コミット先
  • リモートリポジトリ・・・プッシュ先(実質オンライン上のコミット先)
  • push・・・リモートリポジトリへアップロード
  • fetch・・・リモートリポジトリからダウンロード(リモートから更新情報の取得するだけ)
  • Fast-Forward・・・mergeの種類、リモートの更新情報をローカルに反映
  • Non Fast-Forward・・・mergeの種類、ブランチの合流
  • rebase・・・ブランチの根本のコミットを変える・付け替え、新しいコミットにしてしまう
    • 混乱の元あまり使わないが吉
  • pull・・・fetch+merge
  • origin・・・リモートリポジトリのことを指す
  • origin/masterブランチ・・・このブランチはローカルリポジトリにある
    • リモートリポジトリのmasterブランチから見るとリモート追跡ブランチである
    • ローカルのmasterブランチから見ると上流ブランチである
  • ハッシュ・・・復号ができない暗号のようなもの

リモート追跡ブランチ・・・ローカルリポジトリにあって、他のリポジトリの状態を追跡するブランチ、git fetch すると更新される

Git基礎

$ git init
$ git add 〇〇
$ git commit -m "first commit"
$ git log --oneline #一行表示
9cdf5er (HEAD -> master) first commit

git logの一行表示の参考記事👈参考させていただいた記事

$ git branch
* master
$ git branch develop #ブランチ作成
$ git branch
  develop #増えてる
* master
$ git checkout develop
$ git branch
* develop
  master

※Git 2.28 以降なら git config --global init.defaultBranch で init 時に作られる branch を変更できる。

Non Fast-Forwardのmerge・・・GitHubでPullRequest使ってるから使うことはなさそう
git merge <theirs>oursにcheckoutしてる状態でmerge
ours・・・mergeされるbranch
theirs・・・mergeするbranch

$ git branch
  develop
* master
$ git merge develop
$ git branch
* master

チームで使う

gitとは分散型のVCでリポジトリの全履歴を含めた完全なコピーをローカルにもつ👉コンフリクトが起こるからbranchの運用はしっかりする
集中型はリポジトリは完全にサーバーが管理しており、自分が触っているファイルにはpushされるまで他人が編集を加えることができない👉開発速度が遅い

GitFlowというbranch運用があり、集中型と分散型のいいとこ取りができる
息の長いブランチは悪さするのですぐマージしてまた切ってを繰り返す方が吉

GitHub

Issues・・・相談事や課題を書く場所、マイルストーンをつけたり、誰かをassignしたり色々できる
Pull requests・・・margeではなくpullという名前なのはfork元(コピー元)にお願いする機能だから、fork元から見るとpullの形(git rebaseとかを使ってコミットをきれいにするとレビューしやすい!)
Acrions・・・GitHubが出してるCI/CD環境
Projects・・・カンバンスタイルのタスク管理ツール
Wiki・・・ちょっとしたFAQやチーム文化などを書くところ、あまり使わない?
Security・・・脆弱性報告の手順を書いたり、非公開issueなどを作成できたり、依存パッケージの脆弱性アラートを飛ばしてくれたりもする
Insights・・・時系列でコミット数や差分の量がグラフ化されてたりする
Settings・・・リポジトリの設定を変更できる

Gitの内部構造

commitまでの流れ

  1. コードを編集する
  2. 編集したコードをaddする
  3. commitする

add

add は基本的にblobオブジェクトの生成をし、.git/indexに保存する(を更新する)

Gitはオブジェクトと呼ばれる概念でデータを表現している
※branchなどオブジェクトで管理してないものもある

オブジェクトは4種類
blobオブジェクト・・・ファイルの情報
treeオブジェクト・・・ディレクトリの情報
commitオブジェクト・・・コミットの情報
tagオブジェクト・・・anntated tagの情報(名前付きタグ)

オブジェクトは.git/objectsの中にzlib形式圧縮されて保存されている
git cat-file -p コミットハッシュでオブジェクトの中身を直接確認

blobオブジェクトはadd時に作成
addでディレクトリが追加されてもtreeオブジェクトは作らず、blobオブジェクトしか作らない。

commit

tree オブジェクトはcommit時に作成

merkle-treeというデータ構造

白がblobオブジェクトでファイルに相当
青がtreeオブジェクトでディレクトリに相当
ファイル名のようなメタデータはtreeオブジェクトが管理する

commitオブジェクトはtreeオブジェクトが作成された後、に作成

commit オブジェクトに含まれている情報は4つ

  • リポジトリのルートディレクトリのtreeハッシュ
  • 親commitのハッシュ・・・※1
  • CommitterとAuthorのタイムスタンプ・名前・メアド・・・※2
  • コミットメッセージ

※1 悪意のあるcommitの改ざんを防ぐ
一つのcommitを改ざんしても以降全てのcommitを改ざん必要があり、commitハッシュを計算するだけで過去の履歴全てがvalidであることを証明できる👉Gitはブロックチェーン

※2 Author:オリジナルのコードを書いた人、Committer:コミットをした人
Gitはrebaseなどで歴史を改変できるので、commit --amend などを行っても、オリジナルのコードを書いたのが誰かがわかるようにAuthorが変更されない

commitオブジェクトが作成された後、HEADの参照先を最新のコミットオブジェクトに進める

tag,branch,HEADはrefs

refsとは・・・ハッシュの参照を持っており、オブジェクトや他のrefsを参照できる
HEADはbranchのハッシュを持っており、そのbranchはcommitのハッシュを参照している
checkoutするとHEADが書き変わり参照先が変わる

GitのHEADとは何者なのか👈参考させていただいた記事
HEADとは・・・今自分が作業している場所を示すポインタ、ブランチを示すポインタ
ブランチとは・・・コミットを示すポインタ、ブランチが作られた場合は単に新しいポインタが作られるだけ

まとめるとコミットは。。。

  1. コードを編集する
  2. 編集したコードをaddする
    • blobオブジェクトの生成
    • indexの更新
  3. commitする
    • treeオブジェクトの生成
    • commitオブジェクトの生成
    • HEADの書き換え
    • 各種Hooksの起動・・・対応するイベントが発火したときに実行してくれるスクリプト
    • reflogの更新・・・HEAD の向き先の移動履歴を書き込む、git reflogで確認できる
    • COMMIT_EDITMSG(ファイル)の編集・・・このファイルに書き込まれている内容が、コミットメッセージとして commitオブジェクトに取り込まれる

コミットが繰り返されるごとブランチは次のブランチに自動で移動し、HEADも移動する

checkout

  1. 指定したcommitが参照しているtreeをワークツリーに展開する
  2. indexをワークツリーと同期する(=treeと同じ状態にする)
  3. HEADを指定したcommitに変更する(refsを指定していた場合、HEADにはその参照が書き込まれる)

reset

$ git reset オプション
--soft <commit ハッシュ>・・・直前のコミット内容を修正
--mixed <commit ハッシュ>・・・ステージしたものを取り消す、オプション無しでも同じ結果
--hard <commit ハッシュ>・・・指定したコミットまでワークツリーごと削除

resetしてもHEAD・index・ワークツリーを書き換えるコマンドのため、commitオブジェクトを削除するわけではない👉どこからも参照されていないcommitが出来上がる

👉そういうオブジェクトは一定期間経つと、git gcというコマンドが走って消される。
👉どこからも参照されていないオブジェクトは git fsckで探せる

reset後、githubにも反映させるには$ git push -f origin リポジトリ名が必要
👉現在いるブランチにプッシュするならリポジトリ名は省略可

GitHubで編集を提案

Discussion