Git 実用小抄#
Git - 愚かなコンテンツトラッカー。
プロジェクト開発の過程で、Git は非常に便利なバージョン管理ツールです。これにより、開発者は時間や場所に関係なく効率的に協力できます。本記事では、Git の基本的な使い方を簡単に説明し、効率を上げるための小さなヒントや Git のワークフローのブランチ管理について紹介します。
よく使う Git コマンド#
git status#
git status
を使用して、インデックス(index)と作業ディレクトリ(workspace)の状態を確認します。ここで見ることができるのは:
- 現在のブランチ
- 未追跡のファイル
- 修正されたファイル
- ステージされたファイル
- 追加情報
頻繁にgit status
を使用することで、リポジトリの状態を常に把握できます。
git add#
git add
コマンドを使用して、指定したファイルをインデックス(index)に追加します。git status
と併用することをお勧めし、コミットログの説明範囲外のファイルや.gitignore
ファイルに無視されていないファイルがコミットされないように、追加する変更を慎重に確認してください。
git commit#
git commit
を使用して、変更をローカルリポジトリ(repository)にコミットします。Git は各コミットに説明を追加することを強制します。コミット後に「間違ってコミットした!」と気づいた場合は、git reset
を使用して復元するか、git commit --amend
を使用して最新のコミットを修正できます。新しいコミットを記録することを気にしない場合は、git revert
を使用して新しいコミットを生成し、変更を元に戻すこともできます。git commit
の情報は規範的に記入するべきで、コミットログを見ればそのコミットがどのような変更を行ったかがわかるのが理想です。
git commit 規範#
規範はコミットログの意味がプロジェクトの履歴を追跡可能にし、コードを更新する際に最小限のコストでコミット情報を取得できることにあります —— この更新がどのような変更を行ったかを知るためです。コミットログでは、できるだけ三つの次元でコミットを説明することを推奨します:type(タイプ)、scope(範囲)、subject(概要)。
type(必須項目)#
type はコミットの提出タイプを表します。履歴を追跡する際、まず type でフィルタリングすることで、かなりの時間を節約できます。
type(必須) | 英語 | 説明 |
---|---|---|
feat | feature | 新機能追加 |
fix | fix | バグ修正 |
docs | documents | ドキュメント更新 |
style | style | コードスタイル |
refactor | refactor | コードリファクタリング |
perf | performance | パフォーマンス向上 |
test | test | テスト関連 |
build | build | ビルド関連 |
ci | continuous integration | 継続的インテグレーション |
revert | revert | コードを元に戻す |
chore | chore | その他の変更 |
scope(任意項目)#
scope はコミットが変更された範囲を表します。例えば、ビュー層、コントローラー層、モデル層などです。
subject(必須項目)#
subject はコミットの説明を表し、50 文字以内に収めるのが望ましいです。説明はこの変更を正確に記述し、追跡を容易にするべきです。目的を達成するために、コミットの粒度は少し小さくしても良いでしょう。後でgit rebase
を使用して複数のコミットを統合し、コミット記録を整理できます。
良い履歴は見ていて心地よいものです。実際には中国人は subject を中国語で書くことをお勧めします。。。
悪い履歴は見ていて不快です。でも彼は大物だから、彼がこう書くのには理由があるはずです(確信)
git pull#
git pull
を使用して、リモートの変更をローカルリポジトリに同期します。定期的にpull
することをお勧めします。自分が変更しているのが最新のブランチであることを確認できます。未コミットの変更がある場合、git pull
コマンドのマージ部分は失敗し、ローカルブランチは変更されません。したがって、リモートリポジトリから新しいコミットを取得する前に、常にブランチに変更をコミットするべきです。
git pull
の動作モードを完全に理解するためには、二つのコマンドを理解する必要があります:git fetch
とgit merge
git fetch#
git fetch
を使用して、リポジトリ内のすべてのリモートリポジトリの追跡ブランチを更新します。実際には、どのローカル作業ブランチにも変更は反映されません。これは、ローカルリポジトリがリモートリポジトリの更新を認識しただけで、まだ同期は行われていないことを意味します。IDEA
には自動fetch
の関連プラグインがあるので、インストールしてブランチの更新を即座に認識できるようにすることをお勧めします。
git merge#
git merge target-branch
を使用して、ターゲットブランチを現在のブランチにマージします。merge
のマージ戦略には二つの方法があります:fast-forward と三方マージ:
- Fast-forward マージ:二つのブランチ間に変更がない場合、Git はターゲットブランチをソースブランチのコミットオブジェクトに直接指し示します。これがいわゆる Fast-forward マージです。この操作は新しいコミットオブジェクトを作成しません。なぜなら、以前のコミットがすでにすべての変更を含んでいるからです。
-
三方マージ:二つのブランチ間に変更の衝突がある場合、三方マージを行う必要があります。三方マージでは、Git は新しいコミットオブジェクトを作成し、そのオブジェクトには二つのブランチ間の共通点と各ブランチが共通点に対して行った変更が含まれます。Git は衝突を解決して一貫した変更にしようとします。
git push#
git push
を使用して、変更をリモートリポジトリ(remote)にアップロードします。時々コードをpull
することをお勧めします。
その他の実用的な Git コマンド#
git diff#
git diff
を使用して、作業スペースでまだインデックスに追加されていない変更を確認します。git diff --cached
を使用して、インデックスにまだコミットされていない変更を確認します。git diff branch1 branch2
を使用して、二つのブランチ間の差異を確認します。
git stash#
git stash
シリーズのコマンドは、新しい領域 —— スタッシュエントリ(stash entry)をもたらします。git stash push
を使用して、まだコミットされていない変更をスタッシュにプッシュします。作業スペースとインデックスは最新のコミットの変更に戻ります。git stash pop
を使用して、スタッシュのスタックのトップの変更をポップします。git stash list
を使用して、スタッシュに保存された変更のリストを確認します。
git stash
は、pull できない状況を示すためによく使用されます。これは通常、作業スペースやインデックスにまだコミットされていない変更があることを意味します。この場合、まず変更をスタッシュにプッシュし、作業スペースとインデックスを復元し、pull 操作が完了した後に変更をポップします。
git stash
はブランチを切り替えるのにも非常に適しています。例えば、自分が担当しているフィーチャーブランチで開発しているときに、オンラインで突然バグが発生し、修正が必要になった場合、すぐにブランチを master に切り替えて hotfix ブランチを新たに作成する必要があります。しかし、現在の変更はまだコミットされていないため、機能が完成していないため、コミットすることもできません。この場合、git stash
コマンドを使用して変更をスタッシュにプッシュし、ブランチを切り替えて開発し、作業が終わったらスタッシュにプッシュしたときのブランチに戻って変更をポップすれば良いのです。
git rebase#
git rebase
シリーズのコマンドは、私たちのコミットを整理する機会を提供し、履歴をクリーンで明瞭に保ち、履歴を追跡しやすくします。これについて、Vue の作者である尤雨溪は、知乎で次のように述べています:
攻撃的な表現ですね 2333
git rebase target-branch
の本質は、現在のブランチとターゲットブランチの共通の祖先を見つけ、まず現在のブランチの変更を「横に置き」、現在のブランチの履歴コミットをターゲットブランチの履歴コミットと一致させ、その後「横に置いた」コミットを現在のブランチに適用することです。このブランチのマージ戦略は、git merge
との違いは次の通りです:
git merge
は無駄なコミットログ情報を残し、履歴を汚染します。git rebase
は履歴を整理するために、当然ながら現在のブランチのコミットを変更します。したがって、あるブランチで rebase を行った後、そのブランチの順序は以前とは異なります。この時、他の人もそのブランチを使用している場合、彼が push しようとするとエラーが発生する可能性があり、変更が失われることもあります。
したがって、git rebase
は未だにリモートリポジトリに push されていないコミットを修正するためにのみ使用することをお勧めします。また、あなた自身だけが使用するブランチに適用するべきです。
もちろん、git rebase
はブランチをマージするためだけでなく、複数のコミットをマージすることもできます。git rebase -i [startpoint] [endpoint]
を使用して、-i
オプション —— すなわち--interactive
を使用してインタラクティブな編集インターフェースを開きます。ここで[startpoint] [endpoint]
は左開き右閉じの範囲であり、[startpoint]
を指定する必要があります。デフォルトでは[endpoint]
はHEAD
が指すコミットです。例えば、git rebase -i HEAD~3
を使用して最新の 3 回のコミットを編集します。
pick 54f88ff 最初のコミット
pick 41346f3 二回目のコミット
pick 3b9307e 三回目のコミット
# 変基 edb3a72..3b9307e への edb3a72(3つのコミット)
#
# コマンド:
# p, pick <コミット> = コミットを使用
# r, reword <コミット> = コミットを使用するが、コミットの説明を編集
# e, edit <コミット> = コミットを使用するが、コミットを修正するために停止
# s, squash <コミット> = コミットを使用するが、前のコミットに圧縮
# f, fixup [-C | -c] <コミット> = "squash"に似ているが、前のコミットの
# コミット説明のみを保持し、-Cオプションを使用した場合は
# このコミットの説明のみを保持。-cと-Cは似ていますが、
# コミット説明を編集するためにエディタを開きます。
# x, exec <コマンド> = シェルを使用してコマンドを実行(この行の残りの部分)
# b, break = ここで停止('git rebase --continue'を使用して再開)
# d, drop <コミット> = コミットを削除
# l, label <label> = 現在の HEAD にラベルを付ける
# t, reset <label> = HEAD をそのラベルにリセット
# m, merge [-C <コミット> | -c <コミット>] <label> [# <oneline>]
# . マージコミットを作成し、元のマージコミットの説明を使用(指定されていない場合
# . は、コメント部分の oneline をコミット説明として使用)。-c <コミット>を使用すると
# . コミット説明を編集できます。
# u, update-ref <参照> = 参照 <ref> にプレースホルダーを設定し、この場所の新しいコミットに
# その参照を更新します。この <参照> はリベース終了後に更新されます。
#
# これらの行を再配置することができます。上から下に実行されます。
#
# ここで行を削除すると、対応するコミットが失われます。
#
# ただし、すべての内容を削除すると、リベース操作が終了します。
コメントには利用可能なコマンドが詳細に説明されています。このシナリオでは、これらの 3 つのコミットをマージしたいと仮定し、次のように変更します:
r 54f88ff 最初のコミット
f 41346f3 二回目のコミット
f 3b9307e 三回目のコミット
次に、コミットログ情報を変更します:
コンソールに「HelloWorld」を繰り返し出力
# 変更のコミット説明を入力してください。'#'で始まる行は無視され、空のコミット
# 説明はコミットを終了させます。
#
# 日付: Sat Mar 25 11:28:26 2023 +0800
#
# インタラクティブリベース操作が進行中;edb3a72まで
# 最後に実行されたコマンド(1つのコマンドが実行されました):
# reword 54f88ff 最初のコミット
# 次に実行されるコマンド(残り2つのコマンド):
# fixup 41346f3 二回目のコミット
# fixup 3b9307e 三回目のコミット
# あなたは 'master' ブランチを 'edb3a72' にリベースする操作を編集しています。
#
# 提出される変更:
# 修正: HelloWorld.java
変更が完了したら、git log
を確認すると、履歴が正常にマージされていることがわかります:
git rebase
コマンドを使用することで、リモートリポジトリにコミットを push する前に、ローカルリポジトリのコミットを編集、再構成、マージ、整理し、クリーンで整然とした履歴を得ることができます。すでにリモートリポジトリに push されたコミットを変更することは厳禁です!!!
git cherry pick#
git cherry pick
コマンドを使用すると、特定のコミットを現在のブランチに適用することができます。例えば、現在のブランチの状況は次のようです:
今、私はこのコミットを main ブランチに直接適用したいと思っています。入力します:
git cherry pick C2(このコミットのハッシュ値)
これで適用されました。これにより、main ブランチに新しいコミット C2' が作成されます。この二つのコミットの内容は同じですが、ハッシュ値は異なります。
Git ワークフロー#
最後に、Git ワークフローについて簡単に説明します。Git ワークフローは、プロジェクトが異なる状態のコードを隔離するために、さまざまな種類のブランチを組み合わせて迅速なイテレーションを達成する方法を示しています。現在人気のあるブランチモデルには、フィーチャーブランチ開発モデルやマスターブランチ開発モデルなどがあります。
フィーチャーブランチ開発モデル#
- ブランチ管理が複雑;
- 開発サイクルが比較的長い;
- 時間が経つにつれて、master ブランチとの差が大きくなり、最終的には衝突を解決するのが難しくなるか、さらには不可能になる可能性があります。
マスターブランチ開発モデル#
- ブランチ管理が簡単;
- 開発サイクルが非常に短く、新しいバージョンのブランチをいつでもチェックアウトできる;
- コード品質の要求が高い。
最後に#
- Git ツールを習得し、開発効率と協力効率を向上させる;
- よく使ういくつかのコマンド:
add
、commit
、push
、pull
、status
を習得し、[option]
オプションを使用して機能を強化できるようにする; - コミットログの規範は、履歴を追跡しやすくし、プロジェクトの変更を記録するためのものであり、より重要なのは、履歴を確認することでプロジェクトを迅速に理解できるようにすること;
- 定期的に pull する。頻繁に pull することで、最新のブランチで変更していることを確認でき、頻繁にコミットすることで保証できます。最終的に push する際には、rebase を使用して履歴を整理してからリモートリポジトリに push することを考慮する;
- stash スタッシュを使用して、緊急のコード切り替え時にコミットを忘れてコードが汚染されるのを防ぐ;
- 実際に使用するブランチモデルに基づいて行動する。一度決定したら、積極的に実行するべきであり、そうでなければ破窓理論により、良好なブランチ管理が破壊され、プロジェクトの品質とイテレーション速度が保証されなくなります。
関連リンク
ただ git log しか知らない? 実は git には他にも便利な log コマンドがある