Lock in $30 Savings on PRO—Offer Ends Soon! ⏳

Git 以前の話

Git 以前の話

ZIP でバックアップを管理している人に贈る Git へのいざない

Avatar for Yoshinari Nomura

Yoshinari Nomura

June 14, 2023
Tweet

Other Decks in Programming

Transcript

  1. (要求) ある時点ごとの状態をバックアップしながら開発したい バージョン管理システム(VCS)前夜 3 file0: A-0 file1: B-0 file2: C-0

    • file0 の内容 (A-0) を編集したい • その前に現状を保存しておきたい ワーキングディレクトリ file0:A-0 file1: B-0 file2: C-0
  2. 4 file0:A-0 file1: B-0 file2: C-0 Version01.zip 安心して編集: A0→A1 スナップショット

    <スナップショット> ある時点の全ファイルを保存 したもの スナップショットを保存しておく ワーキングディレクトリ file0:A-1 file1: B-0 file2: C-0
  3. 5 file0: A-0 file1: B-0 file2: C-0 file0: A-1 file1:

    B-0 file2: C-0 file0: A-1 file1: B-0 file2: C-1 Version01.zip Version02.zip 編集中 VCS いらずの簡単管理!! ワーキングディレクトリ ZIP 方式と命名しよう
  4. ZIP方式の欠点 6 簡単.分かりやすい.特別なツール不要.だけど… • ファイル名とバージョンの関係を管理できない ◦ Version02: 上司へ提出バージョン ◦ Version03:

    上司の指摘で修正バージョン ◦ Version??: 大幅書換バージョン ◦ Version??: 大幅書換に上司の指摘も合わせたバージョン ◦ 元に戻し,その理由を記したバージョン • 共同作業が面倒 ◦ Alice と Bob が独自に Version02.zip を作ってしまう ◦ フォルダの共有管理が面倒 • Version02.zip がなんだったのか思い出せない ◦ 「上司へ提出」等のメモ (ログ) を残したい • バージョン間の差を比較し辛い ◦ 比較する専用のコマンドとかあれば…
  5. 7 バージョンの関係は有向グラフ I H G F E A B C

    D DAG (Directed Acyclic Graph): 有向非巡回グラフ 元となるバージョン(親)を「←」で指す • D: 上司へ提出バージョン • E: 上司の指摘で修正バージョン • F: 上司の指摘で更に修正バージョン • G: 大幅書換バージョン • H: 大幅書換バージョンに上司の指摘も合わせたバージョン ファイルの名前付けやメモでこの関係を表すのは難しい <ちなみに Git では> • 個々のバージョンを「コミット」と呼ぶ • 上記のコミット間の関係を表すグラフを「コミットグラフ」と呼ぶ
  6. ZIP方式の改善案 8 * commit 958b60dcd90a5180620dde45a25895b56a109060 ← ハッシュ |\ Merge: 9f5bdad

    7433837 ← 親への連結 | | Author: Alice | | Date: Fri Jun 9 11:50:24 2023 +0900 | | | | Merge pull request #129 from bob/dev | | Delete “AT” command notification | | | * commit 7433837f8180321bb92ab0887456b5c193999682 |/ Author: Bob | Date: Mon May 29 10:04:31 2023 +0900 | | Delete “AT” command notification | * commit 9f5bdad9bc527b244a493e3c9cd5b283946ff675 • Alice と Bob が共に Version002.zip を作ってしまう → 解決 • ファイル名とバージョンの関係を管理できない → 解決 • ファイル名をハッシュ関数を使って作れば被らない 例: 958b60dcd90a5180620dde45a25895b56a109060.zip みたいな • バージョン間の関係は親への連結を別途管理する 958b60dcd90a518…5895b56a109060.zip の作り方?
  7. 958b60d…a109060.zip の作り方 9 (1) 以下のような commit.txt を作って ZIP に同梱する (2)

    作った ZIP (tmp.zip) の SHA-1 ハッシュを計算する sha1sum tmp.zip → 958b60dcd90a5180620dde45a25895b56a109060 (3) tmp.zip のファイル名を変更する mv tmp.zip 958b60dcd90a5180620dde45a25895b56a109060.zip parent 9f5bdad9bc527b244a493e3c9cd5b283946ff675 ← 親1 parent 7433837f8180321bb92ab0887456b5c193999682 ← 親2 author Yoshinari Nomura <[email protected]> ← 変更した人 大幅書換に上司の指摘もマージした ← メッセージ (ログ) • ファイル名とバージョンの関係を管理できない → 解決 • Alice と Bob が Version02.zip を作ってしまう → 解決 • “上司へ提出” 等のメッセージ(ログ)を残したい → 解決 New!
  8. 名前にハッシュ関数を使う意義 10 • ZIP 内のファイルが1つでも違えばハッシュ値が異なる ◦ 逆に同じ内容なら同じハッシュ値なので,Bob と Alice が同じ

    内容の ZIP (コミット) を持つかの判断が楽 ◦ 相手が持ってないコミットを渡すだけで共有できる • ハッシュ値計算に commit.txt も入っている ◦ parent, author, メッセージが違えば,異なるハッシュ値 ◦ Alice & Bob が偶然全く同じ内容に変更しても区別される ◦ 変更の理由等が異なる → 同一コンテンツでも別の物 ▪ 一度変更 → 何らかの理由で戻す状況を保存できる 958b60d…a109060.zip と同等の物を作るのを自動化するのが Git 以降,「コミット」という単語が出てきたら,958b60d…a109060.zip の こと,あるいはそれを作る行為だと思えば,大体合ってます
  9. Git の機能の一部 11 git init: コミット保存場所 (.git ディレクトリ) を作成 git

    add: .git 内の zip 作るゾーン (Index) にファイルをコピー git commit: Index からコミットを作成 git log: commit.txt 等を親子系列で表示 git checkout: 特定のコミット(zip)をワーキングディレクトリに展開 git diff: コミット間の差分を表示 Alice & Bob のやりとり: (多くの場合は Alice の代わりに GitHub だったりする) bob> git clone: Alice の全コミットを Bob に転送 bob> git push: Alice が持ってないコミットを Alice に送信 bob> git fetch: 持ってないコミットをAliceから受信
  10. 疑問1: コミットの親をどう指定する? 12 現在の親 (最初はNULL) は,.git/HEAD というファイルで管理されてい て,git commit 実行時に自動で参照されます.

    git commit 後,HEAD の値は,今作ったコミットを示すように自動で 変更されます.したがって,git commit を続ける限りは,親を意識す る必要がありません. HEAD のことを Git では「シンボリック参照」と呼びます. git checkout は,親 (HEAD) を換える働きもあります.親を変更して コミットを作ることで,一直線ではないグラフを作れます. 複数の親を指定する merge という操作には,git merge コマンドが利 用できます.
  11. 疑問2: コミットIDを記憶すべき? 13 Git には,コミットID (ハッシュ値) に別名を付ける機能があります. 1つは,タグといって,特定のコミットに名前を付けます.例えば ,74...9682 に

    Version1 というタグを付け,リリースの目印にしま す. もう1つは,ブランチです.特定のコミットに名前を付ける点はタグと 同じですが,タグは Version1 = 74...9682 の関係が固定的ですが,ブ ランチは,git commit などを契機に動きます.これはHEAD と似てま すね.実は,HEAD は,特定のブランチの別名です. ブランチは,コミットを契機に動くので,開発の流れ (支流) を複数管 理したいときにその先端への目印として付けます.master や main,development といった名前が通常使われます. git branch というコマンドで特定のコミットに develop といった名前 を付けられます.
  12. 疑問3: 1コミットなのにブランチ? 14 Git は,たった1つのコミットを (例えば master) 名前で参照して,そ れを master

    ブランチ(枝) と呼びますが,なぜでしょうか. これは,コミットが有向非巡回グラフを作っていることに起因します. ブランチ,つまりある特定のコミットを指定すれば,そこに至るのに必 要だった全コミットが分かります.つまりコミット1つは,その歴史と 同じ意味を持ちます.git のブランチは単なるポインタなので操作が軽 量 だといわれる理由です. これまでの説明で Git のイメージがつかめたでしょうか.つかめていれ ば,以下が何をしているか説明できると思います. git checkout develop git add file1.txt git commit -m ‘file1を追加したよ’
  13. おわりに 15 • 実際の Git は,もう少し賢い方法でファイルを管理します ◦ まるごと ZIP でなく,同じファイルはポインタにするなど

    ◦ これ (オブジェクトストア) の理解には永続データ構造の知 識が役立つでしょう. • 主要な概念は,ここで説明した事と同じです ◦ このスライドを理解できれば,Git で何をしているのか不安 になることは少ないでしょう. • 巷には,Git のコミットがファイル差分だといった誤解で説明さ れている Web ページもあります. • できるだけ原典か,定評のある本などを参照しましょう ◦ たとえば Git 本家の https://git-scm.com/book/ja/v2 がお すすめです.