Git編

はじめる前に

Git(ギット)について学習していきます。 まずは、以下の動画で仕組みについて学習しましょう。

Git学習準備

環境

Git設定

Gitを初期設定のままインストールを進めると
テキストファイルの改行コードが自動変換される設定になります。
自動変換されないように「core.autocrlf」に「false」を設定しておきます。

git config --global core.autocrlf false

core.autocrlf」設定値は3種類あり、Windowsはデフォルトの改行コードがCRLFになるため
設定値によって以下のように変換されます。

core.autocrlf git checkout git commit 備考
true LF -> CRLF CRLF -> LF ほぼ使われない設定
input - CRLF -> LF 開発する際に便利な設定
稀に問題が発生するケースあり
false - - 自動変換が行われないので安全
コーディングの際の改行コードは自身で確認が必要

Linux環境で動作するPHP等では改行コードは「LF」とされているため
PHPファイルの改行コードは「LF」とされています(参照:PSR-12 ~ 2.2 Files)。

VSCode拡張機能

Gitを扱うための拡張機能をご紹介します。

GitHub

まず、自身のアカウントでリポジトリをGitHub上で作成しましょう。

リポジトリ作成

developブランチ作成

ブランチ設定

※ 今回は、学習のための保護設定にしてあります。
 学習外にはなりますが、その他のブランチルールについては公式を参照してください。
 https://docs.github.com/ja/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/managing-a-branch-protection-rule

タグ作成

今回は不要ですが、開発準備が完了した時点(Laravelだとインストール直後のソースコード等)でタグの作成を行います。
タグに関しては、管理者が行うことが多いので学習外とし詳細説明を割愛します。
コマンドでつける場合、「git tag」コマンドで行います。
GitHub公式では、以下のような案内があります。

Tagging suggestions
It’s common practice to prefix your version names with the letter v. Some good tag names might be v1.0.0 or v2.3.4.

If the tag isn’t meant for production use, add a pre-release version after the version name. Some good pre-release versions might be v0.2.0-alpha or v5.9-beta.3.

Semantic versioning
If you’re new to releasing software, we highly recommend to learn more about semantic versioning.

A newly published release will automatically be labeled as the latest release for this repository.

If 'Set as the latest release' is unchecked, the latest release will be determined by higher semantic version and creation date. Learn more about release settings.

タグの付け方
v1.0.0やv2.3.4といったタグ名が良いでしょう。

もし、そのタグが本番用でない場合、バージョン名の後にプレリリースバージョンを追加してください。プレリリースのバージョンには、v0.2.0-alphaやv5.9-beta.3などがあります。

意味論的バージョニング
もしあなたがソフトウェアのリリースに慣れていないのであれば、セマンティック・バージョニングについて学ぶことを強くお勧めします。

新しく公開されたリリースは、自動的にこのリポジトリの最新リリースとしてラベル付けされます。

最新リリースとして設定する」のチェックが外れている場合、最新リリースはより高いセマンティックバージョンと作成日付によって決定されます。リリース設定の詳細については、こちらをご覧ください。

リモートリポジトリ複製

git_clone_image PlantUML

リモートリポジトリ(GitHub上のリポジトリ)をローカルに複製します。

ローカルディレクトリ準備

複製先を用意します。
実務でも複数リポジトリ(複数プロジェクト)を扱う事は、よくあるので
混同しないよう、リポジトリ毎にディレクトリを分けるようにしましょう。
training-gitディレクトリは、複製時に作られるため
現時点では不要です。

URL取得

git clone

※ 注意: Git管理上のディレクトリ内(trainingリポジトリのディレクトリ等)でgit cloneをするのは避けて下さい。**

Git Bash」等のターミナルで、任意の場所に 「git clone "★URL"」を実行しましょう(上記の例の場合、個人アカウントディレクトリで実行)。
URLはGitHub上で取得したものを使用します。

git_clone

VSCodeで出来あがった「training_git」フォルダを開きましょう。
ターミナルは、Windowsであれば「Git Bash」を選択してください。
Git Graph」は任意ですが表示方法は以下になります。

vscode_training_git

Git学習シナリオ

現場のGit運用については「git flow」や「github flow」をベースにすることが多いかと思います。
今回は「git flow」を簡単にしたものを想定して実際にGit操作していきましょう。

シナリオ

以下はプロジェクト開始~リリースまでのブランチの流れを表しています。
開発者はあなたを含めて2名で、あなたはA機能を担当
もう1名はB機能を担当します。

簡易図

Mermaid
git_flow_simple_for_mermaid

詳細

PlantUML
git_flow_simple

  Mainへのマージ Developへのマージ push 概要
Main - × Production branch
本番リリース用ブランチ
他のブランチへのマージは、障害があった場合を除いて行われません。
Develop PRによるマージ - × Development branch
開発ブランチ
Feature × PRによるマージ 開発ブランチ(機能・課題毎に分ける)

featureブランチの作成

A機能の実装を開始するため「Feature」ブランチを、リモートリポジトリの「Develop」ブランチから作成します。

git_new_branch_feature_a PlantUML

作成する前に「git fetch」コマンドにより、ローカルリポジトリを最新の状態にします。
チームで作業している場合、自分が作業している間に変更が加えられている可能性があるためです。

# リモートリポジトリの最新をローカルリポジトリに取り込む
git fetch
# 「develop」リモートブランチから「feature/a」ブランチを作成
git checkout -b feature/a origin/develop

git_new_branch_feature_a

originとは

リモートリポジトリの名前(デフォルト名)と覚えておきましょう。
git clone」コマンドを実行すると、デフォルトの「origin」が設定されます。

詳細については割愛しますが、先ほどの「origin/{ブランチ名}」はリモートトラッキングブランチ(追跡ブランチ)と言って、厳密にはリモートブランチではありません
git fetch」を実行することで「origin/{ブランチ名}」はリモートブランチと同じ状態になると覚えてください。

A機能

A機能の実装・テストに入りましょう。

git_imp_feature_a PlantUML

A機能実装

まずは、A機能を実装します。
A機能はWEBページとしますので「htdocs/a.html」を適当に追加しましょう。

git_imp_feature_a

A機能テスト

A機能のテストをします。
テストと言ってもウォーターフォールで言う単体テストではなく、実装フェーズ内のセルフチェックです。
今回はシンプルな機能なので割愛しますが
実際は以下のような確認を行います。

A機能コミット

動作に問題なければローカルブランチにコミットします。
コミットに関しては変更内容を確認しながら行うため
コマンドラインでやることは少ないので、VSCodeでの方法をご紹介します。
コマンドラインで行う方法も覚えておきましょう。

vscode_git_add_and_commit

# VSCodeの「変更をステージ」と同様
git add htdocs/a.html
# VSCodeの「ステージされている変更」をコミット
git commit -m ":sparkles: htdocs/a.html"

※ コミットメッセージの「:sparkles:」は絵文字を表します。
※ この時点ではGitHubには反映されません。

B機能

ここで一旦、B機能(Bさん)の作業を行いましょう。
A機能と平行で進めていると仮定します。

git_imp_feature_b PlantUML

B機能実装

まずは、GitHubでFeatureブランチを作成します。

github_create_feature_b

次にB機能を実装します。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>B機能</title>
</head>
<body>
    B機能
</body>
</html>

github_commit_changes

上記の要領で「htdocs/index.html」もコミットしてください。
ファイル内容は以下にしてください。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Home</title>
</head>
<body>
    <nav>
        <ul>
            <li><a href="b.html">B画面</a></li>
        </ul>
    </nav>
</body>
</html>

B機能テスト

テストは割愛します。

B機能PR作成

以下の手順でPRを作成します。

B機能PRマージ

実際はレビューが通ったらマージを行いますが
今回はそのままマージします。

以上の手順で「develop」ブランチにB機能が実装されました。
A機能の作業に戻りましょう。

develop取り込み

feature/a」ブランチに「develop」ブランチの取り込みを行いましょう。

git_merge_or_rebase PlantUML

A機能のpush前に、トップ画面の「htdocs/index.html」にA画面へのリンクを追加することになりました。
ですが「feature/a」ブランチにはトップ画面がないため、「develop」ブランチの取り込みを行います。

まずは「git fetch」を実行し、Graphを見てみましょう。

git fetch

git_fetch_git_graph

上記のGraphの通り、「develop」ブランチから「feature/a」ブランチを作成した後に
develop」ブランチに2つのコミットが入っていることがわかります(マージコミットを除く)。

develop」を取り込む方法はいくつかあります。

  1. マージする
  2. リベースする

やり方は以下を見ていきましょう。
スクリーンショットではリベースでの手順で行っていきます。

マージする場合

シンプルな方法で「develop」を「feature/a」ブランチにマージするだけです。

# 現在のブランチを確認(feature/a)
git branch --show-current
# 現在のブランチに「develop」をマージ
git merge origin/develop

リベースする場合

最新の「develop」をベースにコミットを再適用します。

push前であれば、こちらの方法が使えます。
既にpushしていた場合、コンフリクト(競合)しそうな場合
リベースに関してよくわからない場合はマージを選択することをおすすめします。

# 現在のブランチを確認(feature/a)
git branch --show-current
# 現在のブランチを最新「develop」の上にリベース
git pull --rebase origin develop

git_pull_rebase

上記のGraphで分かる通り、最新の「develop」ブランチから「feature/a」ブランチを作成し、「htdocs/a.html」がコミットされたことになっています。
リベースを使うメリットとしては、マージコミットが減って履歴が綺麗になることです。

git pullとは

「git pull」は「git fetch」+「git merge」を一緒にしたコマンドです。
「git pull」に「–rebase」オプションをつけると「git fetch」+「git rebase」を行います。

A機能追加実装

htdocs/index.html」にリンクを追加しましょう。
ソース管理の対象ファイルを選択すると、変更点を確認することが出来ます。

vscode_compare

コマンドで行う場合は「git diff」でも可能です。
表示量が多い場合、抜けられなくなるかと思いますが
「q」を入力することで終了させることが出来ます。

git_diff

git diff」の詳細説明については割愛します。
以下が参考になります。

変更点について問題なければコミットしましょう。

A機能push

A機能の実装(テスト)が終わったら、「feature/a」ブランチをGitHub上に反映させるため、pushしましょう。

git_push PlantUML

以下、コマンドを実行することで、GitHubに反映されます。

# 現在のブランチを確認(feature/a)
git branch --show-current
# 現在のブランチをリモートにアップ
git push -u origin feature/a

-u」オプションは「--set-upstream」の省略形で
簡単に言うと、リモートブランチへの参照を設定する事が出来て
以降、「feature/a」ブランチは引数なしで「git push」、「git pull」等を行うことが出来るようになります。

A機能PR→マージ

feature/a」ブランチを「develop」にマージするPRを作成し、マージをします。

github_pr_merge PlantUML

PR作成

GitHub上の操作になりますが「develop」ブランチへのマージPRを作成します。

以上でPR作成できました。
実際には他のメンバーにレビューを依頼します。

PRマージ

実際はレビューが通ったら(Approveされたら)マージを行いますが
今回はそのままマージします。

以上の手順で「develop」ブランチにA機能が実装されました。

ブランチ整理

feature/a」ブランチが「develop」ブランチにマージされ
feature/a」ブランチが削除されました。
ですが、ローカルブランチはまだ存在しています。
ブランチを綺麗にしていきましょう。

まずは現在のブランチを「develop」に切り替えます。

# developブランチに切り替え
git checkout develop

次に不要となったブランチを削除していきます。

# 現在のブランチを確認(develop)
git branch --show-current
# developを最新化しつつ、不要となった origin/feature/a を削除
git pull -p
# ローカルの feature/a を削除
git branch -d feature/a
# ブランチ確認(Featureブランチが消えた)
git branch -a

最終的なブランチの状態は以下になります(リベースを選択した場合)。

vscode_develop

一括でローカルブランチを削除する方法

使う場合は自己責任

Linuxコマンドの xargs を使うとまとめて削除が可能です(Git BashのインストールでWindowsでも使用可能)。
オプションを「-D」にするとマージ前のブランチも対象になります。

git checkout develop
# 現在のブランチ以外のローカルブランチを削除
git branch | grep "^ " | xargs git branch -D

エラーが出ても気にならなければ、以下でも可能。

git checkout develop
# 現在のブランチも対象になるため、必ずエラーが発生
git branch | xargs git branch -D

上記で「main」等も対象になりますが
リモートブランチが削除されるわけではないので
git checkout main」を実行すると再生成されます。

リリースまで

実装完了後は「develop」ブランチで単体テスト・結合テスト・システムテスト等を行い
main」ブランチへのPR→マージを行った後にリリースします。
今回は、Git研修のため割愛します。

その他

コンフリクト

今回のシナリオではやりませんでしたが
複数人が同じファイルの同じ箇所を修正することにより
コンフリクト(競合)が発生することがあります。

コンフリクトの解消方法については動画・サイトの記事を参考にしてください。
GitHubで解消することも出来ます。

Gitコミットメッセージ

最後にコミットメッセージについて、深く学習しておきましょう。

Gitコミットメッセージフォーマット

基本的には以下のフォーマットでコミットメッセージを作成します。

<summary>

<description>

例えば以下のようなイメージです。

Update README.md

・〇〇ディレクトリ構成の変更に伴い、README.mdのリンクを修正

適切な履歴の作り方

以下、必ず意識するようにしましょう。

現場でのコミットメッセージ

現場・プロジェクトによってメッセージのルールが異なるため
自身で確認する必要があります。

Gitコミットメッセージの例1

プロジェクトによってルールが異なるため、参考として一つの例を挙げます。

Gitに限らず、その他のバージョン管理システムも同様ですが
summaryには後で検索しやすいように動詞を先頭に持っていくルールが多いです。
例では英語ですが、「Add ◯◯機能」、「Fix タイポ」など日本語のメッセージも可能です。

動詞 読み方 / 意味 説明
Add アッド / 追加する コード追加 Add default value to Helper::exec method.
Update アップデート / 更新する 更新 Update CHANGELOG
Remove リムーブ / 除去する コードを削除(ファイルの削除、1行削除した場合など) Remove lang directory by default
Move ムーブ / 移動する コードを移動 Move middleware.
Fix フィックス / 修理する バグ修正、typo(タイプミス)の修正等 Fix conflicts
Fix typo
Rename リネーム / 改名する 名称変更(ファイル名、変数名等) Rename property 'name' -> 'userName'

また、以下のように#12をメッセージに含めると、GitHub上でPRの12番のリンクが自動的に追加されます。
PRでの指摘対応の際に使用することができ、修正理由が明確になります。
そのため、担当者が変わった場合でも、コミットメッセージからコミットした経緯の追跡ができます。

Fix typo(#12)

Gitコミットメッセージの例2

上記の例では、文字を使ったPrefix(接頭辞)でしたが
以下は絵文字を使ったPrefixです。

Gitコミットメッセージ実務でのルール

筆者が経験したルールや、実際のプロジェクトに適用されているルールです。

Redmine

プロジェクト管理ツールのRedmineと組み合わせている場合
refsキーワードを使ってチケットと紐付けを行うことがあります。

refs #1234 : ◯◯追加

Angular

下記は、実際のAngularプロジェクトで運用されているルールです。

<type>(<scope>): <short summary>`

Gitコミットメッセージの参考資料

おわり

以上でGit研修は終わりです。
追加機能やテストの際に発生したバグ改修については
再度「develop」からブランチを切って行います。
ここまでのシナリオについてはあくまでも1例に過ぎません。

実際「git flow」で運用する現場もあり、それをカスタマイズし、更に複雑化している現場もありました。
逆に「github flow」のようなシンプルな運用もあるかもしれません。
ここまで実際にやってみたことで、冒頭での動画を
再度見ると理解が深まるかと思います。

Gitコマンド

それぞれ使い方についてはHELPを参照したり、WEBで検索してください。

コマンド 備考
git clone "★URL" リモートリポジトリをローカルに複製
git checkout "★ブランチ名" ブランチ切り替え
git checkout -b "★ブランチ名" 新しいブランチを生成してチェックアウト
git push -u origin "★ブランチ名" 初回push時に使用(-u--set-upstream の省略)
git push  
git pull git fetch」+「git merge
git pull --rebase origin "★ブランチ名" git fetch」+「git rebase
git fetch -p リモートリポジトリで削除されたブランチをローカルに反映
git status  
git merge "★ブランチ名" 指定ブランチを現在ブランチにマージする。
基本マージはPRで行うので、このコマンドを使う際は注意
主に派生元のブランチを取り込む場合に使用する。
git cherry-pick "★コミットID" 別ブランチのコミットを適用するのに使用
コンフィグ、定数クラス等軽いコミットの取り込みに使う
git log -n5 --oneline コミットログを1コミット1行で、最新の5件表示する
1番左に出ている7桁の文字列はコミットIDを短くしたもの
git diff "★コミットID" "★コミットID" 指定したコミットの差分を表示する
表示内容が多くなるため、中断する場合は「q」を押すと抜けられる。
git commit --allow-empty -m "★コミットメッセージ" 空コミットが可能、ブランチやプロジェクトの開始を表すコミットで使うことがある。
使うかは現場次第
git branch -D "★ブランチ名" ローカルブランチ削除(-D--delete –force の省略)
git stash 操作が複雑なので以下を参照
https://qiita.com/chihiro/items/f373873d5c2dfbd03250

Gitチートシート

参考