Git Reset と Reflog

GitGitBeginner

💡 このチュートリアルは英語版からAIによって翻訳されています。原文を確認するには、 ここをクリックしてください

はじめに

ようこそ、Git タイムトラベラーの皆さん!本日は、リポジトリの履歴をこれまでにないほど制御できる 2 つの強力な Git 機能、git resetgit reflog について探求します。これらのツールは、Git タイムマシンの高度なコントロールのようなもので、プロジェクトのさまざまな状態間を移動したり、「失われた」作業を回復したりすることができます。

git reset コマンドは、変更を元に戻したり、ファイルのステージングを解除したり、コミット履歴を書き換えたりするのに役立つ多用途なツールです。しかし、大きな力には大きな責任が伴い、git reset は初心者には少し手ごわいかもしれません。そこで git reflog が登場します。これは安全ネットのようなもので、リポジトリの refs (ブランチの先端など) に対して行ったすべての変更を追跡し、最も劇的なリセットからも回復できるようにします。

この実験(Lab)では、以下を扱います。

  1. Soft Reset (ソフトリセット): ワーキングディレクトリやステージングエリアを変更せずに HEAD を移動する
  2. Mixed Reset (ミックスリセット): 変更をワーキングディレクトリに残したまま、ステージングを解除する
  3. Hard Reset (ハードリセット): 変更を完全に破棄する
  4. Reflog を使用して「破壊的」な操作から回復する
  5. Time-based Resets (時間ベースのリセット): 特定の時点の状態にリポジトリを移動する

この実験(Lab)の終わりには、これらの強力な Git 機能を安全かつ効果的に使用する方法をしっかりと理解できるようになります。必要に応じていつでも戻ることができることを知っているので、自信を持ってリポジトリの履歴を操作できるようになります。

さあ、git resetreflog をマスターしましょう!

これは Guided Lab です。学習と実践を支援するためのステップバイステップの指示を提供します。各ステップを完了し、実践的な経験を積むために、指示に注意深く従ってください。過去のデータによると、この 初級 レベルの実験の完了率は 98%です。学習者から 100% の好評価を得ています。

ワークスペースの設定

リセットと reflog を始める前に、実験用のコミットをいくつか含むワークスペースを設定しましょう。新しいディレクトリを作成し、Git リポジトリを初期化し、複数のコミットを含むファイルをいくつか追加します。

ターミナルを開き、次のコマンドを入力します。

cd ~/project
mkdir git-reset-lab
cd git-reset-lab
git init

次に、いくつかのファイルを作成し、一連のコミットを行います。次のコマンドをコピーしてターミナルに貼り付けます。

echo "## Git Reset and Reflog Lab" > README.md
git add README.md
git commit -m "Initial commit"

echo "function add(a, b) { return a + b; }" > math.js
git add math.js
git commit -m "Add addition function"

echo "function subtract(a, b) { return a - b; }" >> math.js
git add math.js
git commit -m "Add subtraction function"

echo "function multiply(a, b) { return a * b; }" >> math.js
git add math.js
git commit -m "Add multiplication function"

今行ったことを分解してみましょう。

  1. README ファイルを作成し、最初のコミットを行いました。
  2. 加算関数を含む JavaScript ファイルを作成し、コミットしました。
  3. 同じファイルに減算関数を追加し、コミットしました。
  4. 最後に、乗算関数を追加し、コミットしました。

これで、実験できる履歴を持つリポジトリができました!

Soft Reset: HEAD の移動

最初に探求するリセットの種類は、「soft (ソフト)」リセットです。ソフトリセットは、HEAD (および現在のブランチ) を別のコミットに移動しますが、ステージングエリアやワーキングディレクトリは変更しません。これは、いくつかのコミットを「元に戻し」たいが、すべての変更を新しいコミットのために保持しておきたい場合に役立ちます。

ソフトリセットを試してみましょう。

git reset --soft HEAD~2

このコマンドは、HEAD を 2 つのコミット前に移動します (「Add subtraction function」の前のコミットに)。~2 は「現在の HEAD の 2 つ前のコミット」を意味します。~N を使用して、N 個前のコミットに戻ることができます。

ここで、git status を実行すると、「Add subtraction function」と「Add multiplication function」のコミットからの変更が一緒にステージングされていることがわかります。ワーキングディレクトリ内のファイルは変更されていません。これらの 2 つのコミットからのすべての作業は、1 つの新しいコミットとしてコミットする準備ができています。

これは、最後のいくつかのコミットを 1 つに「まとめる」場合に役立ちます。いくつかのコミットまでソフトリセットし、それらのすべての変更を含む新しいコミットを作成できます。

これらの変更を新しいメッセージで再度コミットしましょう。

git commit -m "Add subtraction and multiplication functions"

ソフトリセットは、一般的に安全ですが (変更を破棄しないため)、履歴を書き換えることに注意してください。元のコミットを既にプッシュしている場合は、リモートブランチを更新するために強制プッシュを行う必要があり、これは共同作業者に問題を引き起こす可能性があります。共有履歴を書き換える前に、必ずチームとコミュニケーションを取りましょう!

Mixed Reset: 変更のステージング解除

次に見ていくリセットの種類は、「mixed (ミックス)」リセットです。これは、フラグを指定しない場合、git reset のデフォルトモードです。ミックスリセットは、HEAD を移動し、ステージングエリアを一致するように更新しますが、ワーキングディレクトリには触れません。

いくつかの変更を行い、ステージングしてみましょう。

echo "function divide(a, b) { return a / b; }" >> math.js
git add math.js

ここで、気が変わり、この変更をまだステージングしたくないとしましょう。ミックスリセットを使用できます。

git reset HEAD

これにより、変更のステージングが解除されますが、ワーキングディレクトリには保持されます。ここで git status を実行すると、math.js が変更されているが、ステージングされていないことがわかります。

ミックスリセットは、いくつかの変更をステージングしたが、まだコミットする準備ができていないと判断した場合に役立ちます。変更を再度確認したり、ステージングする前にさらに修正を加えたりしたい場合があります。

ソフトリセットとは異なり、ミックスリセットはステージングエリアを変更することに注意してください。ただし、作業を破棄しないという意味では安全です。すべてがまだワーキングディレクトリにあります。

Hard Reset: 変更の破棄

3 番目で最も過激なリセットの種類は、「hard (ハード)」リセットです。ハードリセットは、HEAD を移動し、ステージングエリアを更新し、さらにワーキングディレクトリを一致するように更新します。これは、リセット先のコミット以降のすべての変更を破棄することを意味します。

ハードリセットを試してみましょう。

git add math.js
git commit -m "Add division function"
git status
git reset --hard HEAD~1

これにより、除算関数がステージングおよびコミットされ、前のコミットへのハードリセットが実行され、事実上最後のコミットが「取り消され」、変更が破棄されます。

math.js を見ると、除算関数がなくなっていることがわかります。まるで、一度も書かなかったかのようです。

ハードリセットは強力ですが、危険です。いくつかの作業を完全に破棄し、以前のコミットからやり直したい場合に役立ちます。ただし、変更を完全に破棄する可能性があるため、非常に注意してください。

ハードリセットを実行する前に、必ず正しいコミットにリセットしていることを再確認してください。不明な場合は、ソフトリセットまたはミックスリセットを使用するか、実験する前に新しいブランチを作成する方が安全です。

Reflog を使用して失われたコミットを復元する

さて、除算関数を破棄するつもりはなかったことに気づいた場合はどうでしょうか?ここで git reflog が役立ちます。reflog は、HEAD がローカルリポジトリ内で移動したすべての場所のログです。リセットのような履歴を書き換えるコマンドでさえ記録する、スーパー履歴のようなものです。

reflog を見てみましょう。

git reflog

リセットなど、最近行ったすべての操作のリストが表示されるはずです。各エントリには HEAD@{n} 識別子があります。

失われたコミットを復元するには、ハードリセット前の状態にリセットできます。

git reset --hard HEAD@{1}

これにより、最後の操作(ハードリセット)前の HEAD の状態にリセットされます。

math.js を確認すると、除算関数が戻っているはずです!

cat math.js
function add(a, b) { return a + b; }
function subtract(a, b) { return a - b; }
function multiply(a, b) { return a * b; }
function divide(a, b) { return a / b; }

reflog は強力なセーフティネットであり、ほぼすべての Git の事故から回復できます。ただし、これはマシンローカルであり、一時的であることに注意してください(エントリは通常 30 ~ 90 日間保持されます)。これは、定期的なバックアップや、作業をリモートリポジトリにプッシュすることの代わりにはなりません。

時間ベースのリセット

Git では、特定の時点でのリポジトリの状態にリセットすることもできます。これは、リポジトリが戻りたい状態にあったおおよその時間を覚えている場合に役立ちます。

時間ベースのリセットを試してみましょう。

git reset --hard master@{"1 hour ago"}

これにより、リポジトリが 1 時間前の状態にリセットされます。「yesterday (昨日)」、「2 days ago (2 日前)」、「3 minutes ago (3 分前)」など、さまざまな時間記述子を使用できます。

時間ベースのリセットは、特定のコミットへのリセットよりも精度が低い可能性があるため、注意が必要です。意図した場所に到達したことを確認するために、時間ベースのリセット後に必ずリポジトリの状態を確認してください。

期待した結果が得られなかった場合は、reflog を使用して時間ベースのリセットをいつでも元に戻すことができることを覚えておいてください。

まとめ

おめでとうございます、Git タイムロード!Git の最も強力で、潜在的に危険なコマンドのいくつかを習得しました。これまでにカバーした主要な概念を振り返ってみましょう。

  1. Soft Reset (ソフトリセット): HEAD を移動しますが、ステージングエリアやワーキングディレクトリは変更しません。コミットをまとめるのに役立ちます。
  2. Mixed Reset (ミックスリセット): HEAD を移動し、ステージングエリアを更新しますが、ワーキングディレクトリは変更しません。変更をアンステージするのに最適です。
  3. Hard Reset (ハードリセット): HEAD を移動し、ステージングエリアを更新し、ワーキングディレクトリを更新します。強力ですが、破壊的な可能性があります。
  4. Reflog (reflog): HEAD へのすべての変更を記録するセーフティネットであり、ほぼすべての Git の事故から回復できます。
  5. Time-based Resets (時間ベースのリセット): 特定の時点でのリポジトリの状態にリセットできます。

覚えておいてください、大きな力には大きな責任が伴います。これらのコマンドは、リポジトリの履歴を非常に細かく制御できますが、不用意に使用すると危険な場合もあります。リセット、特にハードリセットを実行する前に、常に再確認し、問題が発生した場合は reflog が役立つことを覚えておいてください。

Git の旅を続ける中で、これらのコマンドに慣れるまで、安全な環境で練習してください。これらは、正しく使用すれば、Git のワークフローを大幅に強化できる強力なツールです。

ハッピーリセット、そしてあなたの Git 履歴が常にクリーンで意味のあるものになりますように!