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 規範#
規範は、コミットログの意義がプロジェクトの履歴を追跡可能にし、コードを更新する際に最小限のコストでコミット情報を取得できるようにするためにあります —— この更新でどのような変更が行われたかを把握するためです。コミットログでは、できるだけ 3 つの次元でコミットを説明することをお勧めします: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
の動作モードを完全に理解するためには、2 つのコマンドを理解する必要があります:git fetch
とgit merge
git fetch#
git fetch
を使用して、リポジトリ内のすべてのリモートリポジトリの追跡ブランチを更新します。実際には、ローカルの作業ブランチには何の変更も反映されません。これは、ローカルリポジトリがリモートリポジトリの更新を認識しただけで、まだ同期は行われていないことを意味します。IDEA
には自動fetch
の関連プラグインがあり、インストールしてブランチの更新を即座に感知することをお勧めします。
git merge#
git merge target-branch
を使用して、ターゲットブランチを現在のブランチにマージします。merge
のマージ戦略には 2 つの方法があります:fast-forward と三方マージ:
- Fast-forward マージ もし 2 つのブランチ間に変更がなければ、Git はターゲットブランチをソースブランチのコミットオブジェクトに直接指し示します。これがいわゆる Fast-forward マージです。この操作は新しいコミットオブジェクトを作成しません。なぜなら、以前のコミットがすでにすべての変更を含んでいるからです。
-
三方マージ もし 2 つのブランチ間に変更の衝突がある場合、三方マージを行う必要があります。三方マージでは、Git は新しいコミットオブジェクトを作成し、そのオブジェクトには 2 つのブランチ間の共通点と各ブランチが共通点に対して行った変更が含まれます。Git はまた、衝突を一貫した変更として解決しようとします。
git push#
git push
を使用して、変更をリモートリポジトリにアップロードします。時々コードをpull
することをお勧めします。
その他の実用的な Git コマンド#
git diff#
git diff
を使用して、作業スペースでまだインデックスに追加されていない変更を確認します;git diff --cached
を使用して、インデックスにまだコミットされていない変更を確認します;git diff branch1 branch2
を使用して、2 つのブランチ間の差異を確認します。
git stash#
git stash
シリーズのコマンドは、新しい領域 —— スタッシュエントリ(stash entry)を提供します。git stash push
を使用して、まだコミットしていない変更をスタッシュにプッシュします。これにより、作業スペースとインデックスは最新のコミットの変更に戻ります。git stash pop
を使用して、スタッシュのスタックのトップの変更をポップします。git stash list
を使用して、スタッシュに保存された変更のリストを確認します。
git stash
は、プルできない状況を示すためによく使用されます。これは通常、作業スペースまたはインデックスにまだコミットされていない変更があることを意味します。この場合、変更をスタッシュにプッシュして作業スペースとインデックスを復元し、プル操作が完了した後に変更をポップすることができます。
git stash
はブランチを切り替えるのにも適しています。例えば、自分が担当しているフィーチャーブランチで開発しているときに、オンラインで突然バグが発生し、修正する必要がある場合、すぐにブランチをマスターに切り替えてホットフィックスブランチを新たに作成する必要があります。しかし、現在の変更はまだコミットされていないため、機能が完成していないため、コミットすることもできません。この場合、git stash
コマンドを使用して変更をスタッシュにプッシュし、ブランチを切り替えて開発を行い、作業が完了したらスタッシュに戻って変更をポップすればよいのです。
git rebase#
git rebase
シリーズのコマンドは、私たちのコミットを整理する機会を提供し、履歴をクリーンで明瞭にし、非常に追跡しやすくします。これについて、Vue の作者である尤雨溪は知乎で次のように述べています:
攻撃的な表現ですね 2333
git rebase target-branch
の本質は、現在のブランチとターゲットブランチの共通の祖先を見つけ、まず現在のブランチの変更を「脇に置き」、現在のブランチの履歴コミットをターゲットブランチの履歴コミットと一致させ、その後「脇に置いた」コミットを現在のブランチに適用することです。このブランチをマージする戦略は、git merge
との違いは以下の通りです:
git merge
は無駄なコミットログ情報を残し、履歴を汚染します。git rebase
は履歴を整理するために、当然ながら現在のブランチのコミットを変更します。したがって、1 つのブランチ上で、rebase を行った後、このブランチの順序は以前とは異なります。この時、他の誰かがこのブランチ上で作業していると、彼がプッシュする際にエラーが発生する可能性があり、変更が失われることもあります。
したがって、git rebase
は未だにリモートリポジトリにプッシュされていないコミットを修正するため、または自分だけが使用するブランチに適用するためにのみ使用することをお勧めします。
もちろん、git rebase
はブランチをマージするためだけでなく、複数のコミットをマージするためにも使用できます。git rebase -i [startpoint] [endpoint]
を使用して、-i
オプション —— つまり--interactive
を使用してインタラクティブな編集インターフェースを開きます。ここで[startpoint] [endpoint]
は左開き右閉じの範囲であり、[startpoint]
を指定する必要があります。デフォルトでは[endpoint]
はHEAD
が指すコミットです。例えば、git rebase -i HEAD~3
を使用して最新の 3 つのコミットを編集します。
pick 54f88ff 初回のコミット
pick 41346f3 2回目のコミット
pick 3b9307e 3回目のコミット
# 変基 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 2回目のコミット
f 3b9307e 3回目のコミット
次に、コミットログ情報を変更します:
コンソールに「HelloWorld」を繰り返し出力
# 変更のコミットメッセージを入力してください。'#'で始まる行は無視され、空のコミット
# メッセージはコミットを終了します。
#
# 日付: Sat Mar 25 11:28:26 2023 +0800
#
# インタラクティブリベース操作が進行中;edb3a72 まで
# 最後に実行されたコマンド(1つのコマンドが実行されました):
# reword 54f88ff 初回のコミット
# 次に実行されるコマンド(残り2つのコマンド):
# fixup 41346f3 2回目のコミット
# fixup 3b9307e 3回目のコミット
# 'master'ブランチを'edb3a72'にリベースする操作中にコミットを編集しています。
#
# 提出する変更:
# 修正: HelloWorld.java
変更が完了した後、git log
を確認すると、履歴が正常にマージされています:
git rebase
コマンドを使用することで、リモートリポジトリにコミットをプッシュする前に、ローカルリポジトリのコミットを編集、再構成、マージ、整理し、クリーンで整然とした履歴を得ることができます。すでにリモートリポジトリにプッシュされたコミットを変更することは避けるべきです!!!
git cherry pick#
git cherry pick
コマンドを使用すると、特定のコミットを現在のブランチに適用することができます。例えば、現在のブランチの状況は次の通りです:
今、このコミットを直接メインブランチに適用したいとします。次のように入力します:
git cherry pick C2(このコミットのハッシュ値)
これで適用され、メインブランチに新しいコミット C2' が作成されます。この 2 つのコミットの内容は同じですが、ハッシュ値は異なります。
Git ワークフロー#
最後に、Git ワークフローについて簡単に説明します。Git ワークフローは、プロジェクトが異なる状態のコードを隔離するために、さまざまな種類のブランチを組み合わせて迅速なイテレーションを達成する方法を示しています。現在人気のあるブランチモデルには、フィーチャーブランチ開発モデルや、メイン開発モデルなどがあります。
フィーチャーブランチ開発モデル#
- ブランチ管理が複雑;
- 開発サイクルが相対的に長い;
- 時間が経つにつれて、master ブランチとのギャップが大きくなり、最終的には衝突を解決するのが難しくなるか、さらには不可能になることもあります。
メイン開発モデル#
- ブランチ管理が簡単;
- 開発サイクルが非常に短く、新しいバージョンのブランチをいつでもチェックアウトできる;
- コード品質の要求が高い。
最後に#
- Git ツールを習得し、開発効率と協力効率を向上させる;
- よく使うコマンド:
add
、commit
、push
、pull
、status
を習得し、[option]
オプションを使用して機能を強化できるようにする; - コミットログの規範は、履歴を追跡しやすくし、プロジェクトの変更を記録するためのものであり、さらに重要なのは、履歴を確認することでプロジェクトを迅速に理解できるようにするためです;
- 定期的にプルする。頻繁にプルすることで、最新のブランチで変更していることを保証し、頻繁にコミットすることでそれを確保できます。最後にプッシュする際には、リベースを通じて履歴を整理してからリモートリポジトリにプッシュすることを考慮するべきです;
- スタッシュを使用して、緊急のコード切り替え時にコミットを忘れてコードの汚染を防ぐ;
- 実際に使用するブランチモデルに基づいて行動する。一度決定したら、積極的に実行するべきです。そうしないと、破窓理論により、良好なブランチ管理が破壊され、プロジェクトの品質とイテレーション速度が保証されなくなります。
関連リンク
git log だけしか使えない? 実は git には他にも便利な log コマンドが 2 つある