1. 序章

特定の時点にロールバックする場合でも、特に厄介なコミットを元に戻す場合でも、Gitの使用中にコミットを元に戻すか元に戻す必要があることがよくあります。 このチュートリアルでは、Gitでコミットを元に戻したり元に戻したりするための最も一般的なコマンドについて説明します。 また、これらのコマンドの機能に微妙な違いがあることも示します。

2. gitcheckoutを使用した古いコミットの確認

まず、 git checkout コマンドを使用して、特定のコミットでのプロジェクトの状態を確認できます。 git log コマンドを使用して、Gitリポジトリの履歴を確認できます。 各コミットには一意のSHA-1識別ハッシュがあり、タイムライン内のコミットを再確認するために gitcheckoutで使用できます。

この例では、 e0390cd8d75dc0f1115ca9f350ac1a27fddba67d の識別ハッシュを持つコミットを再検討します。

git checkout e0390cd8d75dc0f1115ca9f350ac1a27fddba67d

作業ディレクトリは、指定したコミットの正確な状態と一致するようになります。 したがって、プロジェクトを履歴状態で表示し、現在のプロジェクト状態を失うことを心配せずにファイルを編集できます。ここで行うことは何もリポジトリに保存されません。 これは、切り離されたHEAD状態として知られています。

ローカルで変更されたファイルでgitcheckout を使用して、それらを作業コピーバージョンに復元できます。

3. gitrevertを使用してコミットを元に戻す

git revert コマンドを使用して、Gitでコミットを元に戻します。 このコマンドは従来の元に戻す操作ではないことを覚えておくことが重要です。 代わりに、コミットによって導入された変更を反転し、逆の内容で新しいコミットを生成します。

つまり、 git revert は、特定のcommitの逆を適用する場合にのみ使用する必要があります。 後続のすべてのコミットを削除しても、プロジェクトの以前の状態に戻ることはありません。1つのコミットを元に戻します。

git revert は、元に戻すコミットへのrefポインターを移動しません。これは、 gitcheckoutgitresetなどの他の「undo」コマンドとは対照的です。 ]。 代わりに、これらのコマンドは HEADrefポインターを指定されたコミットに移動します。

コミットを元に戻す例を見てみましょう。

mkdir git_revert_example
cd git_revert_example/
git init .
touch test_file
echo "Test content" >> test_file 
git add test_file
git commit -m "Adding content to test file"
echo "More test content" >> test_file 
git add test_file
git commit -m "Adding more test content"
git log
git revert e0390cd8d75dc0f1115ca9f350ac1a27fddba67d
cat test_file

この例では、test_fileを作成し、コンテンツを追加して、コミットしました。 次に、 git log を実行して、元に戻すコミットの commit hash を識別する前に、ファイルにコンテンツを追加してコミットしました。

この例では、最新のコミットを元に戻しています。 最後に、 git revert を実行し、ファイルの内容を出力することでコミットの変更が元に戻されたことを確認しました。

4. gitresetで以前のプロジェクト状態に戻す

Gitを使用するプロジェクトで以前の状態に戻すには、 gitresetコマンドを使用します。 このツールは、より複雑な変更を元に戻します。 これには、Gitの内部状態管理システムに関連する3つの主要な呼び出し形式があります。 –hard –soft 、および –mixedです。 使用する呼び出しを理解することは、 gitrevertを実行する上で最も複雑な部分です。

git reset は、 gitcheckoutと動作が似ています。 ただし、 git reset はHEADrefポインターを移動しますが、gitcheckoutはHEADrefポインターを操作し、それを移動しません

さまざまな呼び出しを理解するために、Gitの内部状態管理システム —Gitの3つのツリーとも呼ばれます。

最初のツリーは作業ディレクトリです。 このツリーはローカルファイルシステムと同期しており、ファイルおよびディレクトリのコンテンツに加えられた即時の変更を表します。

次に、ステージングインデックスツリーがあります。 このツリーは、作業ディレクトリの変更を追跡します。つまり、 git add で選択された変更は、次のコミットに保存されます。

最後のツリーはコミット履歴です。 git commit コマンドは、 commithistoryに保存されている永続的なスナップショットに変更を追加します。

4.1. –ハード

この呼び出しで最も危険で頻繁に使用されるオプションは、指定されたコミットに更新するためのコミット履歴参照ポインターです。 この後、ステージングインデックス作業インデックスは、指定されたコミットのインデックスと一致するようにリセットされます。 ステージングインデックスおよび作業ディレクトリに対する以前に保留中の変更は、コミットツリーの状態に一致するようにリセットされます。 ステージングインデックスと作業インデックスの保留中またはコミットされていない作業はすべて失われます。

上記の例に続いて、ファイルにさらにコンテンツをコミットし、リポジトリに新しいファイルをコミットしてみましょう。

echo "Text to be committed" >> test_file
git add test_file
touch new_test_file
git add new_test_file
git commit -m "More text added to test_file, added new_test_file"

次に、リポジトリ内の最初のコミットに戻すことにしたとします。 これは、次のコマンドを実行することで実現できます。

git reset --hard 9d6bedfd771f73373348f8337cf60915372d7954

Gitは、HEADが指定されたコミットハッシュにあることを通知します。 test_file の内容を見ると、最新のテキスト追加が存在せず、new_test_fileが存在しないことがわかります。 このデータ損失は元に戻せないため、 –hardがGitの3つのツリーでどのように機能するかを理解することが重要です。

4.2. –ソフト

–soft で呼び出しが発生すると、refポインターが更新され、そこでリセットが停止します。 したがって、ステージングインデックス作業ディレクトリは同じ状態のままになります。

前の例では、–soft引数を使用した場合、ステージングインデックスにコミットした変更は削除されませんでした。 ステージングインデックスで変更をコミットすることは引き続き可能です。

4.3. –混合

デフォルトの動作モードでは、引数が渡されない場合、 –mixed は、 –soft–hardの呼び出しの中間になります。 ステージングインデックスは、指定されたコミットおよび参照ポインター更新の状態にリセットされます。 ステージングインデックスから取り消された変更は、作業ディレクトリに移動します。

上記の例で–mixed を使用することは、ファイルへのローカル変更が削除されないことを意味します。 ただし、 –soft とは異なり、変更はステージングインデックスから取り消され、次のアクションを待ちます。

5. 結論

2つの方法を比較する簡単な方法は、 git revertは安全であり、gitresetは危険ですです。 この例で見たように、 gitresetで作業が失われる可能性があります。 git revert を使用すると、パブリックコミットを安全に元に戻すことができますが、 git reset は、作業ディレクトリおよびステージングインデックスのローカル変更を元に戻すように調整されています。

gitresetHEAD refポインターを移動しますが、 git revert は単にコミットを元に戻し、新しいコミットを介してHEAD[に元に戻すを適用します。 X167X]。 また、後続のスナップショットが共有リポジトリにプッシュされた場合は、gitresetを使用しないでください。 他の開発者は公開されたコミットに依存していると想定する必要があります。