注:GitとMercurialの最大の違いの1つは、インデックスまたはステージング領域が明示的に存在することです。
MercurialのGitのユーザーのために:
Gitは、インデックスまたはステージング領域の概念を公開する唯一のDistributedSCMです。他の人はそれを実装して非表示にするかもしれませんが、他の場合には、ユーザーはそれに気づいても対処する必要もありません。
Mercurialのおおまかな同等物はですDirState
。これは、作業コピーのステータス情報を制御して、次のコミットに含めるファイルを決定します。ただし、いずれの場合も、このファイルは自動的に処理されます。
さらに、コマンドラインでコミットするファイルを指定するか、を使用して、コミット時に選択性を高めることができますRecordExtension
。
インデックスの扱いに不安を感じた場合は、より良いものに切り替えています;-)
コツは、Gitを完全に活用するにはインデックスを理解する必要があるということです。2006年5月のこの記事は当時を思い出させます(そして、それは今でも真実です):
「インデックスを拒否すると、本当にgit自体が拒否されます。」
さて、この記事には、使いやすくなった多くのコマンドが含まれています(内容にあまり依存しないでください;))が、一般的な考え方は残っています。
あなたは新しい機能に取り組んでおり、ファイルに小さな変更を加え始めます。
# working, add a few lines
$ git add myFile
# working, another minor modification
$ git add myFile
この時点で、次のコミットは現在のブランチに2つの小さな変更を加えます
# working, making major modification for the new features
# ... damn! I cannot commit all this in the current branch: nothing would work
$ git commit
この時点でステージング領域(インデックス)に追加された変更のみを記録し、現在作業ディレクトリに表示されている主な変更は記録しません。
$ git branch newFeature_Branch
$ git add myFile
次のコミットでは、新しいブランチ「newFrature_Branch」のその他すべての主要な変更が記録されます。
さて、コミット対話的に、あるいは分割をしている追加する「を介して、Mercurialので利用可能な機能hg record
をインストールする必要があります:」コマンドまたは他の拡張機能RecordExtension
、またはCrecordExtension
。
しかし、これはMercurialの通常のワークフローの一部ではありません。
Gitはコミットを一連の「ファイルコンテンツの変更」と見なし、これらの変更を一度に1つずつ追加できるようにします。
その機能とその結果を調査する必要があります。Gitパワーのほとんど(Mercurialとは対照的に、マージを簡単に元に戻す(または問題を二分する、またはコミットを元に戻す)機能など)は、その「ファイルコンテンツ」パラダイムに由来します。
tonfa(プロファイル内:「Hg dev、pythonist」:数字...)コメントに盛り込まれました:
インデックスには基本的に「gitっぽい」ものはありません。hgは、価値があると見なされた場合、実際に、mq
またはshelve
すでにその一部を実行している場合に、インデックスを使用できます。
ああ少年。ああ、またか。
まず、1つのツールを他のツールよりも美しくするためにここにいるわけではありません。私はHgが素晴らしく、非常に直感的で、優れたサポートがあります(特に、私のプラットフォームであるWindowsでは、LinuxとSolaris8または10でも動作します)。
インデックスは実際には、Linus TorvaldsがVCSで動作する方法の中央にあります。
Gitは、最初のマージを行う前であっても、1日目から明示的なインデックス更新を使用しました。それは単に私がいつも働いてきた方法です。私はダーティツリーを持っている傾向があり、コミットしたくないランダムパッチがツリーにあります。これは、次のバージョンのMakefileの更新にすぎないためです。
これで、インデックス(Gitでのみ見られる概念ではありません)と「コンテンツは王様」というパラダイムの組み合わせにより、かなりユニークで「git風」になります。
gitはコンテンツトラッカーであり、ファイル名はコンテンツに関連付けられていない限り意味がありません。したがって、git add filenameの正しい動作は、ファイルのコンテンツとその名前をインデックスに追加することだけです。
注:ここでの「コンテンツ」は次のように定義されています。
Gitのインデックスは基本的に次のように定義されています
- ツリーの「コンテンツ」全体を含めるのに十分です(これにはすべてのメタデータが含まれます:ファイル名、モード、およびファイルコンテンツはすべて「コンテンツ」の一部であり、それら自体はすべて無意味です!)
- 明白で些細な(しかし非常に重要な!)ファイルシステム比較の最適化を可能にする追加の「統計」情報。
したがって、実際にはインデックスがコンテンツであると見る必要があります。
内容は別パーツとしての「ファイル名」や「ファイル内容」ではありません。2つを分離することはできません。
ファイル名だけでは意味がありません(ファイルの内容も必要です)。ファイルの内容自体も同様に意味がありません(到達方法を知っている必要があります)。
私が言おうとしていることは、基本的にgitではコンテンツなしでファイル名を表示できないことです。概念全体が狂っており、有効ではありません。「現実」とは無関係です。
よりよくある質問、主な利点は以下のとおりです。
- 細かい粒度でコミット
- コミットされていない変更をかなり長い間ツリーに保持するのに役立ちます
- 1つのコミットに対していくつかの小さなステップを実行し、で何をしたかを確認し
git diff
、git add
またはで各小さなステップを検証しますgit add -u
。
- マージの競合の優れた管理ができます
git diff --base
、git diff --ours
、git diff --theirs
。
git commit --amend
その間にインデックスが変更されていない場合は、ログメッセージのみを修正できます。
私は個人的に、この振る舞いがデフォルトであってはならないと思います、あなたは人々がテストされた、または少なくともコンパイルされた何かをコミットすることを望みます
一般的には正しいですが(「テスト済みまたはコンパイル済み」の部分について)、Gitでブランチとマージ(チェリーピッキングまたはリベース)を使用できるため、一時的なプライベートブランチ(プッシュされた部分のみ)で何度でもコミットできます。リモートの「バックアップ」レポジトリに)、パブリックブランチでこれらの「醜いコミット」を再実行しながら、すべての適切なテストを実施します。