Git-quick-guide
Git-基本概念
バージョン管理システム
- バージョン管理システム(VCS)*は、ソフトウェア開発者が協力して作業の完全な履歴を維持できるようにするソフトウェアです。
以下は、VCSの機能です-
- 開発者が同時に作業できるようにします。
- 互いの変更を上書きすることはできません。
- すべてのバージョンの履歴を保持します。
VCSの種類は次のとおりです-
- 集中型バージョン管理システム(CVCS)。
- 分散/分散バージョン管理システム(DVCS)。
この章では、分散バージョン管理システム、特にGitのみに集中します。 Gitは分散バージョン管理システムに分類されます。
分散バージョン管理システム
集中型バージョン管理システム(CVCS)は、中央サーバーを使用してすべてのファイルを保存し、チームの共同作業を可能にします。 しかし、CVCSの主な欠点は、その単一障害点、つまり中央サーバーの障害です。 残念ながら、中央サーバーが1時間ダウンすると、その時間中は誰もコラボレーションできなくなります。 最悪の場合でも、中央サーバーのディスクが破損し、適切なバックアップが取られていないと、プロジェクトの全履歴が失われます。 ここでは、分散バージョン管理システム(DVCS)が登場します。
DVCSクライアントは、ディレクトリの最新のスナップショットをチェックアウトするだけでなく、リポジトリを完全にミラーリングします。 サーバーがダウンした場合、任意のクライアントのリポジトリをサーバーにコピーして復元することができます。 すべてのチェックアウトは、リポジトリの完全バックアップです。 Gitは中央サーバーに依存しないため、オフラインのときに多くの操作を実行できます。 オフライン時に変更をコミットし、ブランチを作成し、ログを表示し、他の操作を実行できます。 ネットワーク接続が必要なのは、変更を公開して最新の変更を行う場合のみです。
Gitの利点
無料でオープンソース
GitはGPLのオープンソースライセンスの下でリリースされます。 インターネット経由で自由に利用できます。 Gitを使用すると、1円も支払うことなく、プロパティプロジェクトを管理できます。 オープンソースであるため、ソースコードをダウンロードし、要件に応じて変更を行うこともできます。
速くて小さい
ほとんどの操作はローカルで実行されるため、速度の面で大きな利点があります。 Gitは中央サーバーに依存しません。そのため、操作ごとにリモートサーバーと対話する必要はありません。 Gitのコア部分はCで記述されているため、他の高レベル言語に関連する実行時のオーバーヘッドが回避されます。 Gitはリポジトリ全体をミラーリングしますが、クライアント側のデータのサイズは小さくなります。 これは、クライアント側でデータを圧縮および保存する際のGitの効率を示しています。
暗黙的なバックアップ
データのコピーが複数ある場合、データを失う可能性は非常にまれです。 クライアント側に存在するデータはリポジトリをミラーリングするため、クラッシュまたはディスクの破損が発生した場合に使用できます。
セキュリティ
Gitは、セキュアハッシュ関数(SHA1)と呼ばれる一般的な暗号化ハッシュ関数を使用して、データベース内のオブジェクトに名前を付けて識別します。 すべてのファイルとコミットはチェックサムされ、チェックアウト時にチェックサムによって取得されます。 これは、Gitを知らない限り、Gitデータベースからファイル、日付、コミットメッセージおよびその他のデータを変更することは不可能であることを意味します。
強力なハードウェアは不要
CVCSの場合、中央サーバーはチーム全体のリクエストに応えるのに十分強力である必要があります。 小さなチームの場合、これは問題ではありませんが、チームの規模が大きくなると、サーバーのハードウェア制限がパフォーマンスのボトルネックになる可能性があります。 DVCSの場合、開発者は変更をプッシュまたはプルする必要がない限り、サーバーと対話しません。 面倒な作業はすべてクライアント側で行われるため、サーバーのハードウェアは非常にシンプルにできます。
より簡単な分岐
CVCSは安価なコピーメカニズムを使用します。新しいブランチを作成すると、すべてのコードが新しいブランチにコピーされるため、時間がかかり、効率的ではありません。 また、CVCSでのブランチの削除とマージは複雑で時間がかかります。 ただし、Gitによるブランチ管理は非常に簡単です。 ブランチの作成、削除、マージには数秒しかかかりません。
DVCSの用語
ローカルリポジトリ
すべてのVCSツールは、作業用コピーとしてプライベートな職場を提供します。 開発者はプライベートな職場で変更を行い、コミット後、これらの変更はリポジトリの一部になります。 Gitは、リポジトリ全体のプライベートコピーを提供することで、さらに一歩前進します。 ユーザーは、このリポジトリを使用して、ファイルの追加、ファイルの削除、ファイルの名前変更、ファイルの移動、変更のコミットなど、多くの操作を実行できます。
作業ディレクトリとステージング領域またはインデックス
作業ディレクトリは、ファイルがチェックアウトされる場所です。 他のCVCSでは、開発者は通常、変更を行い、変更をリポジトリに直接コミットします。 しかし、Gitは別の戦略を使用します。 Gitは、変更されたすべてのファイルを追跡しません。 操作をコミットするたびに、Gitはステージング領域にあるファイルを探します。 ステージング領域に存在するファイルのみが、すべての変更されたファイルではなく、コミットの対象と見なされます。
Gitの基本的なワークフローを見てみましょう。
- ステップ1 *-作業ディレクトリからファイルを変更します。
- ステップ2 *-これらのファイルをステージング領域に追加します。
- ステップ3 *-ステージング領域からファイルを移動するコミット操作を実行します。 プッシュ操作後、変更はGitリポジトリに永続的に保存されます。
「sort.c」と「search.c」という2つのファイルを変更し、各操作に2つの異なるコミットが必要だとします。 ステージング領域に1つのファイルを追加して、コミットを実行できます。 最初のコミットの後、別のファイルに対して同じ手順を繰り返します。
塊
Blobは* B inary L arge Ob * jectを表します。 ファイルの各バージョンはblobで表されます。 Blobはファイルデータを保持しますが、ファイルに関するメタデータは含みません。 これはバイナリファイルであり、Gitデータベースでは、そのファイルのSHA1ハッシュと呼ばれます。 Gitでは、ファイルは名前でアドレス指定されません。 すべてがコンテンツに対応しています。
木
ツリーは、ディレクトリを表すオブジェクトです。 それは他のサブディレクトリと同様にブロブを保持します。 ツリーは、ツリーオブジェクトの SHA1 ハッシュとも呼ばれるBLOBとツリーへの参照を格納するバイナリファイルです。
コミット
コミットは、リポジトリの現在の状態を保持します。 コミットは SHA1 ハッシュによっても名前が付けられます。 コミットオブジェクトはリンクリストのノードと考えることができます。 すべてのコミットオブジェクトには、親コミットオブジェクトへのポインタがあります。 特定のコミットから、親ポインターを見てコミットの履歴を表示することにより、前に戻ることができます。 コミットに複数の親コミットがある場合、その特定のコミットは2つのブランチをマージすることによって作成されています。
枝
ブランチは、別の開発ラインを作成するために使用されます。 デフォルトでは、Gitにはmasterブランチがあります。これはSubversionのトランクと同じです。 通常、新しい機能で動作するブランチが作成されます。 機能が完成すると、それはmasterブランチにマージされ、ブランチを削除します。 すべてのブランチはHEADによって参照されます。HEADは、ブランチ内の最新のコミットを指します。 コミットを行うたびに、HEADは最新のコミットで更新されます。
Tags
タグは、リポジトリ内の特定のバージョンに意味のある名前を割り当てます。 タグはブランチに非常に似ていますが、違いはタグが不変であることです。 つまり、タグはブランチであり、誰も変更するつもりはありません。 特定のコミット用にタグが作成されると、新しいコミットを作成しても更新されません。 通常、開発者は製品リリース用のタグを作成します。
クローン
クローン操作により、リポジトリのインスタンスが作成されます。 クローン操作は、作業コピーをチェックアウトするだけでなく、リポジトリ全体をミラーリングします。 ユーザーは、このローカルリポジトリを使用して多くの操作を実行できます。 ネットワーキングが関係するのは、リポジトリインスタンスが同期されているときだけです。
Pull
プル操作は、リモートリポジトリインスタンスからローカルインスタンスに変更をコピーします。 プル操作は、2つのリポジトリインスタンス間の同期に使用されます。 これは、Subversionの更新操作と同じです。
Push
プッシュ操作は、ローカルリポジトリインスタンスからリモートインスタンスに変更をコピーします。 これは、変更をGitリポジトリに永続的に保存するために使用されます。 これは、Subversionのコミット操作と同じです。
HEAD
HEADはポインターであり、常にブランチの最新のコミットを指します。 コミットを行うたびに、HEADは最新のコミットで更新されます。 ブランチのヘッドは .git/refs/heads/ ディレクトリに保存されます。
リビジョン
リビジョンは、ソースコードのバージョンを表します。 Gitのリビジョンはコミットによって表されます。 これらのコミットは、 SHA1 セキュアハッシュによって識別されます。
URL
URLはGitリポジトリの場所を表します。 Git URLは設定ファイルに保存されます。
Git-環境設定
Gitを使用する前に、いくつかの基本的な構成変更をインストールして実行する必要があります。 以下は、UbuntuおよびCentos LinuxにGitクライアントをインストールする手順です。
Gitクライアントのインストール
DebianベースのGNU/Linuxディストリビューションを使用している場合、 apt-get コマンドが必要なことを行います。
RPMベースのGNU/Linuxディストリビューションを使用している場合は、 yum コマンドを指定どおりに使用してください。
Git環境をカスタマイズする
Gitはgit configツールを提供します。これにより、構成変数を設定できます。 Gitはすべてのグローバル構成をホームディレクトリにある .gitconfig ファイルに保存します。 これらの構成値をグローバルとして設定するには、-global *オプションを追加し、-global *オプションを省略すると、構成は現在のGitリポジトリに固有になります。
システム全体の構成をセットアップすることもできます。 Gitはこれらの値を /etc/gitconfig ファイルに保存します。このファイルには、システム上のすべてのユーザーとリポジトリの構成が含まれています。 これらの値を設定するには、ルート権限があり、*-system *オプションを使用する必要があります。
上記のコードをコンパイルして実行すると、次の結果が生成されます-
ユーザー名を設定する
この情報は、コミットごとにGitによって使用されます。
メールIDの設定
この情報は、コミットごとにGitによって使用されます。
プルのためのマージコミットを避ける
リモートリポジトリから最新の変更をプルし、これらの変更が異なる場合、デフォルトでGitはマージコミットを作成します。 これは次の設定で回避できます。
色の強調表示
次のコマンドは、コンソールでGitの色の強調表示を有効にします。
デフォルトのエディターの設定
デフォルトでは、Gitはシステムデフォルトエディターを使用します。これは、VISUALまたはEDITOR環境変数から取得されます。 git configを使用して別のものを構成できます。
デフォルトのマージツールの設定
Gitは、競合する変更を作業ツリーに統合するためのデフォルトのマージツールを提供しません。 次の設定を有効にすることで、デフォルトのマージツールを設定できます。
Git設定のリスト
ローカルリポジトリのGit設定を確認するには、以下に示すように git config –list コマンドを使用します。
上記のコマンドは、次の結果を生成します。
Git-ライフサイクル
この章では、Gitのライフサイクルについて説明します。 後の章で、各操作のGitコマンドについて説明します。
一般的なワークフローは次のとおりです-
- Gitリポジトリを作業コピーとして複製します。
- ファイルを追加/編集して作業コピーを変更します。
- 必要に応じて、他の開発者の変更を取得して作業コピーも更新します。
- コミットする前に変更を確認します。
- 変更をコミットします。 すべてが正常であれば、リポジトリに変更をプッシュします。
- コミットした後、何かが間違っていることに気付いた場合は、最後のコミットを修正し、変更をリポジトリにプッシュします。
以下に、ワークフローの図式表現を示します。
Gitチュートリアル Git-create-operation
Git-クローン操作
Gitサーバーにベアリポジトリがあり、Tomも最初のバージョンをプッシュしました。 これで、ジェリーは自分の変更を表示できます。 クローン操作は、リモートリポジトリのインスタンスを作成します。
Jerryは、ホームディレクトリに新しいディレクトリを作成し、クローン操作を実行します。
上記のコマンドは、次の結果を生成します。
Jerryはディレクトリを新しいローカルリポジトリに変更し、ディレクトリの内容をリストします。
Git-変更を実行
Jerryはリポジトリを複製し、基本的な文字列操作を実装することを決定します。 そこで彼はstring.cファイルを作成します。 内容を追加した後、string.cは次のようになります-
彼は自分のコードをコンパイルしてテストしましたが、すべて正常に動作しています。 これで、これらの変更をリポジトリに安全に追加できます。
Gitの追加操作により、ファイルがステージング領域に追加されます。
Gitはファイル名の前に疑問符を表示しています。 明らかに、これらのファイルはGitの一部ではないため、Gitはこれらのファイルをどう処理するのか分からないのです。 そのため、Gitはファイル名の前に疑問符を表示しています。
Jerryはファイルをスタッシュ領域に追加しました。gitstatusコマンドはステージング領域に存在するファイルを表示します。
変更をコミットするために、彼はgit commitコマンドの後に-mオプションを使用しました。 -mオプションを省略した場合。 Gitは、複数行のコミットメッセージを作成できるテキストエディターを開きます。
上記のコマンドは、次の結果を生成します-
ログの詳細を表示することをコミットした後、彼はgit logコマンドを実行します。 コミットのすべての情報と、コミットID、コミットの作成者、コミット日、およびコミットの SHA-1 ハッシュが表示されます。
上記のコマンドは、次の結果を生成します-
Git-変更のレビュー
コミットの詳細を表示した後、Jerryは文字列の長さを負にできないことを認識しているため、my_strlen関数の戻り値の型を変更することにしました。
Jerryは git log コマンドを使用してログの詳細を表示します。
上記のコマンドは、次の結果を生成します。
Jerryは git show コマンドを使用して、コミットの詳細を表示します。 git showコマンドは、パラメーターとして SHA-1 コミットIDを取ります。
上記のコマンドは、次の結果を生成します-
彼は、関数の戻り値の型をintからsize_tに変更します。 コードをテストした後、彼は git diff コマンドを実行して変更をレビューします。
上記のコマンドは、次の結果を生成します-
Git diffでは、新しく追加される行の前に '+' 記号が表示され、削除された行には '-' が表示されます。
Git-変更のコミット
ジェリーはすでに変更をコミットしており、最後のコミットを修正したいと考えています。 この場合、 git amend 操作が役立ちます。 修正操作は、コミットメッセージを含む最後のコミットを変更します。新しいコミットIDを作成します。
操作を修正する前に、彼はコミットログをチェックします。
上記のコマンドは、次の結果を生成します。
Jerryは新しい変更を-修正操作でコミットし、コミットログを表示します。
これで、gitログには新しいコミットIDを持つ新しいコミットメッセージが表示されます-
上記のコマンドは、次の結果を生成します。
Git-プッシュ操作
Jerryは、修正操作を使用して最後のコミットを変更し、変更をプッシュする準備ができました。 プッシュ操作は、Gitリポジトリにデータを永続的に保存します。 プッシュ操作が成功すると、他の開発者はJerryの変更を確認できます。
彼はgit logコマンドを実行して、コミットの詳細を表示します。
上記のコマンドは、次の結果を生成します。
プッシュ操作の前に、彼は変更を確認したいので、 git show コマンドを使用して変更を確認します。
上記のコマンドは、次の結果を生成します。
ジェリーは自分の変更に満足しており、変更をプッシュする準備ができています。
上記のコマンドは、次の結果を生成します。
Jerryの変更がリポジトリに正常にプッシュされました。現在、他の開発者はクローンまたは更新操作を実行して自分の変更を表示できます。
Git-更新操作
既存の機能を変更
トムはクローン操作を実行し、新しいファイルstring.cを見つけます。 彼は誰がこのファイルをリポジトリに追加したか、どのような目的で追加したかを知りたいので、 git log コマンドを実行します。
上記のコマンドは、次の結果を生成します-
クローン操作により、現在の作業ディレクトリ内に新しいディレクトリが作成されます。 彼はディレクトリを新しく作成したディレクトリに変更し、 git log コマンドを実行します。
上記のコマンドは、次の結果を生成します-
ログを観察した後、彼はファイルstring.cが基本的な文字列操作を実装するためにJerryによって追加されたことに気付きました。 彼はジェリーのコードに興味があります。 そこで、彼はstring.cをテキストエディターで開き、すぐにバグを見つけます。 my_strlen関数では、Jerryは定数ポインターを使用していません。 そこで、彼はジェリーのコードを変更することにしました。 変更後、コードは次のようになります-
上記のコマンドは、次の結果を生成します-
テスト後、彼は変更をコミットします。
上記のコマンドは、次の結果を生成します-
トムはgit pushコマンドを使用して変更をプッシュします。
上記のコマンドは、次の結果を生成します-
新しい機能を追加
一方、Jerryは string compare 機能を実装することにしました。 そこで彼はstring.cを変更します。 変更後、ファイルは次のようになります-
上記のコマンドは、次の結果を生成します-
テスト後、彼は変更をプッシュする準備ができています。
プッシュ操作の前に、ログメッセージを表示してコミットを確認します。
上記のコマンドは、次の結果を生成します-
ジェリーは変更に満足しており、変更をプッシュしたいと考えています。
上記のコマンドは、次の結果を生成します-
しかし、GitはJerryが変更をプッシュすることを許可していません。 Gitは、リモートリポジトリとJerryのローカルリポジトリが同期していないと判断したためです。 このため、彼はプロジェクトの歴史を失う可能性があります。 この混乱を避けるため、Gitはこの操作に失敗しました。 現在、ジェリーは最初にローカルリポジトリを更新する必要があり、その後のみ、自分の変更をプッシュできます。
最新の変更を取得する
Jerryはgit pullコマンドを実行して、ローカルリポジトリをリモートリポジトリと同期します。
上記のコマンドは、次の結果を生成します-
プル操作の後、ジェリーはログメッセージをチェックし、コミットID cea2c000f53ba99508c5959e3e12fff493ba6f69 を持つトムのコミットの詳細を見つけます。
上記のコマンドは、次の結果を生成します-
現在、Jerryのローカルリポジトリはリモートリポジトリと完全に同期されています。 したがって、彼は変更を安全にプッシュできます。
上記のコマンドは、次の結果を生成します-
Git-スタッシュ操作
製品に新しい機能を実装するとします。 コードが進行中で、突然顧客のエスカレーションが発生します。 このため、数時間は新しい機能の作業を脇に置いておく必要があります。 部分的なコードをコミットしたり、変更を破棄したりすることはできません。 そのため、部分的な変更を保存し、後でコミットするための一時スペースが必要です。
Gitでは、stash操作は変更された追跡ファイルを取得し、変更をステージングし、いつでも再適用できる未完成の変更のスタックに保存します。
ここで、顧客のエスカレーションのためにブランチを切り替えたいが、まだ取り組んでいるものをコミットしたくない。そのため、変更を隠しておきます。 新しいスタッシュをスタックにプッシュするには、 git stash コマンドを実行します。
これで、作業ディレクトリがクリーンになり、すべての変更がスタックに保存されます。 git status コマンドで確認しましょう。
これで、ブランチを安全に切り替えて他の場所で作業できます。 git stash list コマンドを使用して、隠された変更のリストを表示できます。
顧客のエスカレーションを解決し、半分完了したコードを探して新しい機能に戻ったとします。 git stash pop コマンドを実行して、スタックから変更を削除し、現在の作業ディレクトリに配置します。
上記のコマンドは、次の結果を生成します。
Git-移動操作
名前が示すように、移動操作はディレクトリまたはファイルをある場所から別の場所に移動します。 トムは、ソースコードを src ディレクトリに移動することにしました。 変更されたディレクトリ構造は次のように表示されます-
これらの変更を永続的にするには、変更されたディレクトリ構造をリモートリポジトリにプッシュして、他の開発者がこれを確認できるようにする必要があります。
Jerryのローカルリポジトリでは、プル操作の前に、古いディレクトリ構造が表示されます。
ただし、プル操作の後、ディレクトリ構造は更新されます。 これで、Jerryは src ディレクトリとそのディレクトリ内にあるファイルを見ることができます。
Git-操作の名前変更
今まで、トムとジェリーの両方がプロジェクトをコンパイルするために手動コマンドを使用していました。 現在、ジェリーはプロジェクト用にMakefileを作成し、ファイル「string.c」に適切な名前を付けることにしました。
Gitはファイル名の前に R を表示して、ファイルの名前が変更されたことを示しています。
コミット操作では、Jerryは-aフラグを使用しました。これにより、git commitは変更されたファイルを自動的に検出します。
コミット後、彼は自分の変更をリポジトリにプッシュします。
上記のコマンドは、次の結果を生成します-
現在、他の開発者は、ローカルリポジトリを更新することでこれらの変更を表示できます。
Git-削除操作
トムは自分のローカルリポジトリを更新し、 src ディレクトリでコンパイルされたバイナリを見つけます。 コミットメッセージを表示した後、彼はコンパイルされたバイナリがJerryによって追加されたことに気付きます。
VCSは、実行可能バイナリではなく、ソースコードのみを格納するために使用されます。 そこで、トムはこのファイルをリポジトリから削除することにしました。 さらに操作するために、彼は git rm コマンドを使用します。
コミット後、彼は自分の変更をリポジトリにプッシュします。
上記のコマンドは、次の結果を生成します。
Git-間違いを修正
誤ることは人間です。 そのため、すべてのVCSは、特定のポイントまでミスを修正する機能を提供します。 Gitは、ローカルリポジトリに加えられた変更を取り消すために使用できる機能を提供します。
ユーザーがローカルリポジトリに誤って変更を加えた後、これらの変更を元に戻したいとします。 このような場合、 revert 操作が重要な役割を果たします。
コミットされていない変更を元に戻す
Jerryがローカルリポジトリのファイルを誤って変更したとします。 しかし、彼は変更を元に戻したいと考えています。 この状況に対処するには、 git checkout コマンドを使用できます。 このコマンドを使用して、ファイルの内容を元に戻すことができます。
さらに、 git checkout コマンドを使用して、ローカルリポジトリから削除されたファイルを取得できます。 トムがローカルリポジトリからファイルを削除し、このファイルを元に戻したいとします。 同じコマンドを使用してこれを実現できます。
Gitはファイル名の前に D という文字を表示しています。 これは、ファイルがローカルリポジトリから削除されたことを示します。
注意-コミットする前にこれらすべての操作を実行できます。
ステージング領域から変更を削除
追加操作を実行すると、ファイルがローカルリポジトリから開始領域に移動することがわかりました。 ユーザーが誤ってファイルを変更してステージング領域に追加した場合、 git checkout コマンドを使用して、変更を元に戻すことができます。
Gitには、常に最新のコミットを指す1つのHEADポインターがあります。 ステージング領域からの変更を取り消す場合は、git checkoutコマンドを使用できますが、checkoutコマンドでは、追加のパラメーター、つまりHEADポインターを指定する必要があります。 追加のコミットポインターパラメーターは、git checkoutコマンドに作業ツリーをリセットし、段階的な変更を削除するよう指示します。
トムがローカルリポジトリからファイルを変更するとします。 このファイルのステータスを表示すると、ファイルが変更されたがステージング領域に追加されていないことがわかります。
Gitステータスは、ファイルがステージング領域に存在することを示しています。現在は、git checkoutコマンドを使用してファイルを元に戻し、元に戻したファイルのステータスを表示します。
GitリセットでHEADポインターを移動する
いくつかの変更を行った後、これらの変更を削除することができます。 Gitリセットコマンドは、変更をリセットまたは元に戻すために使用されます。 3種類のリセット操作を実行できます。
以下の図は、Gitリセットコマンドの図的表現を示しています。
Soft
各ブランチには、最新のコミットを指すHEADポインターがあります。 --softオプションの後にコミットIDを指定してGitのリセットコマンドを使用すると、何も破壊せずにHEADポインターのみがリセットされます。
ここで、上記のコミットIDと一致する最新のコミットIDを表示します。
上記のコマンドは、次の結果を生成します。
HEADポインターをリセットしましょう。
ここで、HEADポインターを1ポジションだけリセットします。 .git/refs/heads/master file の内容を確認しましょう。
ファイルのコミットIDが変更されました。コミットメッセージを表示して確認してください。
上記のコマンドは、次の結果を生成します。
混合した
--mixedオプションを使用してGitをリセットすると、まだコミットされていないステージング領域からの変更が元に戻されます。 ステージング領域からの変更のみを元に戻します。 ファイルの作業コピーに加えられた実際の変更は影響を受けません。 デフォルトのGitリセットはgit reset --mixedと同等です。
hard
Gitリセットコマンドで—hardオプションを使用すると、ステージング領域がクリアされます。 HEADポインターを特定のコミットIDの最新のコミットにリセットし、ローカルファイルの変更も削除します。
コミットIDを確認しましょう。
上記のコマンドは、次の結果を生成します。
Jerryは、ファイルの先頭に1行のコメントを追加してファイルを変更しました。
彼はgit statusコマンドを使用してそれを検証しました。
Jerryは変更されたファイルをステージング領域に追加し、git statusコマンドで検証します。
上記のコマンドは、次の結果を生成します。
Gitステータスは、ファイルがステージング領域に存在することを示しています。 次に、--hardオプションでHEADをリセットします。
Gitリセットコマンドが成功しました。これにより、ファイルがステージング領域から戻され、ファイルに加えられたローカルの変更がすべて削除されます。
Gitステータスは、ファイルがステージング領域から元に戻されたことを示しています。
また、headコマンドは、リセット操作によってローカルの変更も削除されたことを示しています。
Git-タグ操作
タグ操作により、リポジトリ内の特定のバージョンに意味のある名前を付けることができます。 トムとジェリーがプロジェクトコードにタグを付けて、後で簡単にアクセスできるようにするとします。
タグを作成する
特定のコミットにタグを付ける場合は、HEADポインターの代わりに適切なCOMMIT IDを使用します。 トムは次のコマンドを使用して、タグをリモートリポジトリにプッシュします。
上記のコマンドは、次の結果を生成します-
タグを表示
トムはタグを作成しました。 これで、Jerryは、-lオプションを指定したGit tagコマンドを使用して、使用可能なすべてのタグを表示できます。
Jerryは、Gitのshowコマンドの後にタグ名を使用して、タグの詳細を表示します。
上記のコマンドは、次の結果を生成します-
タグを削除
トムは次のコマンドを使用して、ローカルおよびリモートのリポジトリからタグを削除します。
Git-パッチ操作
パッチはテキストファイルで、その内容はGit diffと似ていますが、コードとともに、コミットに関するメタデータも含まれています。例:コミットID、日付、コミットメッセージなど コミットからパッチを作成でき、他の人はそれらをリポジトリに適用できます。
Jerryは彼のプロジェクトにstrcat関数を実装しています。 Jerryは自分のコードのパスを作成して、Tomに送信できます。 次に、受け取ったパッチを自分のコードに適用できます。
JerryはGit format-patch コマンドを使用して、最新のコミット用のパッチを作成します。 特定のコミット用のパッチを作成する場合は、format-patchコマンドで COMMIT_ID を使用します。
上記のコマンドは、現在の作業ディレクトリ内に .patch ファイルを作成します。 トムはこのパッチを使用してファイルを変更できます。 Gitは、パッチ* git am および *git apply をそれぞれ適用する2つのコマンドを提供します。 Git apply はコミットを作成せずにローカルファイルを変更し、 git am はファイルを変更してコミットも作成します。
パッチを適用してコミットを作成するには、次のコマンドを使用します-
パッチが正常に適用されると、 git diff コマンドを使用して変更を表示できます。
上記のコマンドは、次の結果を生成します-
Git-ブランチの管理
分岐操作により、別の開発ラインを作成できます。 この操作を使用して、開発プロセスを2つの異なる方向に分岐できます。 たとえば、6.0バージョンの製品をリリースし、7.0の機能の開発を6.0のバグ修正とは別に維持できるようにブランチを作成する場合があります。
ブランチを作成
トムは、git branch <branch name>コマンドを使用して新しいブランチを作成します。 既存のブランチから新しいブランチを作成できます。 特定のコミットまたはタグを開始点として使用できます。 特定のコミットIDが提供されていない場合、開始点としてHEADを使用してブランチが作成されます。
新しいブランチが作成されます。 Tomはgit branchコマンドを使用して、利用可能なブランチを一覧表示しました。 Gitは、現在チェックアウトされているブランチの前にアスタリスクマークを表示します。
ブランチ作成操作の図解は以下に示されています-
ブランチを切り替える
Jerryはgit checkoutコマンドを使用してブランチを切り替えます。
ブランチを作成して切り替えるためのショートカット
上記の例では、2つのコマンドを使用してそれぞれブランチを作成および切り替えています。 Gitはcheckoutコマンドで –b オプションを提供します。この操作により、新しいブランチが作成され、すぐに新しいブランチに切り替わります。
ブランチを削除する
ブランチを削除するには、git branchコマンドで-Dオプションを指定します。 ただし、既存のブランチを削除する前に、他のブランチに切り替えてください。
Jerryは現在 test_branch にいるので、そのブランチを削除したいと考えています。 そこで、彼は以下に示すようにブランチを切り替えてブランチを削除します。
これで、Gitは2つのブランチのみを表示します。
ブランチの名前を変更する
Jerryは、文字列操作プロジェクトでワイド文字のサポートを追加することにしました。 彼はすでに新しいブランチを作成していますが、ブランチ名は適切ではありません。 そのため、 – m オプションの後に* oldブランチ名*と* newブランチ名*を使用してブランチ名を変更します。
これで、git branchコマンドは新しいブランチ名を表示します。
2つのブランチをマージする
Jerryは、ワイド文字列の文字列長を返す関数を実装しています。 新しいコードは次のように表示されます-
上記のコマンドは、次の結果を生成します-
テスト後、彼は変更をコミットして新しいブランチにプッシュします。
Jerryはこれらの変更を新しいブランチにプッシュしているため、 master ブランチの代わりにブランチ名 wchar_support を使用したことに注意してください。
上記のコマンドは、次の結果を生成します。
変更をコミットした後、新しいブランチは次のように表示されます-
トムは、ジェリーがプライベートブランチで何をしているのか興味があり、 wchar_support ブランチのログをチェックします。
上記のコマンドは、次の結果を生成します。
コミットメッセージを表示することにより、トムはジェリーがワイドキャラクター用のstrlen関数を実装し、マスターブランチで同じ機能が必要であることを認識しています。 再実装する代わりに、彼はブランチをマスターブランチにマージして、ジェリーのコードを取ることにしました。
マージ操作の後、マスターブランチは次のように表示されます-
これで、ブランチ wchar_support がmasterブランチにマージされました。 コミットメッセージを表示するか、string_operation.cファイルに加えられた変更を表示することで確認できます。
上記のコマンドは、次の結果を生成します。
テスト後、彼はコードの変更をmasterブランチにプッシュします。
ブランチのリベース
Git rebaseコマンドはブランチマージコマンドですが、違いはコミットの順序を変更することです。
Git mergeコマンドは、他のブランチからのコミットを現在のローカルブランチのHEADの上に配置しようとします。 たとえば、ローカルブランチにコミットA→ B→ C→ Dがあり、マージブランチにコミットA→ B→ X→ Yがある場合、git mergeは現在のローカルブランチをA→のようなものに変換しますB→ C→ D→ X→ Y
Git rebaseコマンドは、現在のローカルブランチとマージブランチ間の共通の祖先を見つけようとします。 次に、現在のローカルブランチのコミットの順序を変更して、コミットをローカルブランチにプッシュします。 たとえば、ローカルブランチにコミットA→ B→ C→ Dがあり、マージブランチにコミットA→ B→ X→ Yがある場合、Gitリベースは現在のローカルブランチをA-のようなものに変換します> B→ X→ Y→ C→ D。
複数の開発者が単一のリモートリポジトリで作業する場合、リモートリポジトリ内のコミットの順序を変更することはできません。 この状況では、リベース操作を使用して、ローカルコミットをリモートリポジトリコミットの上に配置し、これらの変更をプッシュできます。
Git-競合の処理
wchar_supportブランチで変更を実行する
Jerryは wchar_support ブランチに取り組んでいます。 彼は関数の名前を変更し、テスト後に変更をコミットします。
上記のコマンドは、次の結果を生成します-
コードを確認した後、彼は変更をコミットします。
上記のコマンドは、次の結果を生成します-
Master Branchで変更を実行する
一方、マスターブランチでは、トムは同じ関数の名前も変更し、変更をマスターブランチにプッシュします。
上記のコマンドは、次の結果を生成します-
diffを検証した後、彼は変更をコミットします。
上記のコマンドは、次の結果を生成します-
上記のコマンドは、次の結果を生成します-
確認後、彼は変更をコミットします。
上記のコマンドは、次の結果を生成します-
タックルの競合
トムは自分のプライベートブランチでジェリーが何をしているかを見たいので、 wchar_support ブランチから最新の変更をプルしようとしますが、Gitは次のエラーメッセージで操作を中止します。
上記のコマンドは、次の結果を生成します-
競合を解決する
エラーメッセージから、src/string_operations.cに競合があることが明らかです。 彼はgit diffコマンドを実行して、詳細を表示します。
上記のコマンドは、次の結果を生成します-
トムとジェリーの両方が同じ関数の名前を変更したため、Gitは混乱の状態にあり、ユーザーに競合を手動で解決するように求めています。
トムはジェリーが提案した関数名を保持することにしましたが、彼はコメントをそのまま追加しました。 競合マーカーを削除すると、git diffは次のようになります。
上記のコマンドは、次の結果を生成します。
トムはファイルを変更したため、最初にこれらの変更をコミットする必要があり、その後、変更をプルできます。
トムは競合を解決し、プル操作が成功するようになりました。
Git-さまざまなプラットフォーム
GNU/LinuxおよびMac OSは* line-feed(LF)または改行を行末文字として使用しますが、Windowsは line-feedとキャリッジリターン(LFCR)*の組み合わせを使用して行末文字を表します。
これらの行末の違いによる不必要なコミットを回避するには、Gitリポジトリに同じ行末を書き込むようにGitクライアントを構成する必要があります。
Windowsシステムでは、チェックアウト中に行末を CRLF 形式に変換し、コミット操作中に LF 形式に戻すようにGitクライアントを構成できます。 次の設定で必要なことができます。
GNU/LinuxまたはMac OSの場合、チェックアウト操作の実行中に行末を CRLF から LF に変換するようにGitクライアントを構成できます。