Gitで間違いを元に戻すためのガイド(パート2)
公開: 2022-03-10「Gitで間違いを元に戻す」シリーズのこの第2部では、再び勇敢に危険を目の当たりにします。もちろん、首を救うための賢い方法を含む、4つの新しい終末のシナリオを用意しました。 しかし、飛び込む前に、Gitに関する以前の記事をチェックして、Gitでの間違いを元に戻すのに役立つさらに多くのセルフレスキュー方法を確認してください。
さあ行こう!
Reflogを使用して削除されたブランチを回復する
ブランチを削除して、すぐに削除すべきではないことに気付いたことがありますか? 万が一、この気持ちがわからない場合は、良くないと言えます。 悲しみと怒りの混合物があなたに忍び寄りますが、そのブランチのコミットに費やされたすべてのハードワーク、あなたが今失ったすべての貴重なコードについて考えます。
幸いなことに、「Reflog」という名前のGitツールを使用して、そのブランチを死から蘇らせる方法があります。 このツールはシリーズの最初の部分で使用しましたが、ここで少し復習します。Reflogは、Gitがローカルリポジトリ内のHEADポインターのすべての動きを記録するジャーナルのようなものです。 他の、あまりオタクではない言葉:チェックアウト、コミット、マージ、リベース、チェリーピックなどを行うたびに、ジャーナルエントリが作成されます。 これにより、問題が発生した場合のReflogは完璧なセーフティネットになります。
具体的な例を見てみましょう。
$ git branch * feature/login master
現在、ブランチfeature/login
がチェックアウトされていることがわかります。 これが(うっかりして)削除しようとしているブランチだとしましょう。 ただし、その前に、現在のHEADブランチを削除できないため、別のブランチに切り替える必要があります。
$ git checkout master $ git branch -d feature/login
私たちの貴重な機能ブランチはなくなりました—そして(a)私たちの過ちの重大さを理解し、(b)少し悲しむために少し時間を与えます。 涙をぬぐった後、この枝を取り戻す方法を見つける必要があります! Reflogを開いて(単にgit reflog
と入力して)、それが何を保存しているかを確認しましょう。
出力を理解するのに役立つコメントを次に示します。
- まず、Reflogがエントリを時系列で並べ替えることを知っておく必要があります。最新のアイテムがリストの一番上にあります。
- 一番上の(したがって最新の)項目は、ブランチを削除する前に実行した
git checkout
コマンドです。 Reflogが忠実に記録するのは、これらの「HEADポインターの動き」のひとつであるため、ここでReflogに記録されます。 - 重大な間違いを元に戻すには、その前の状態に戻すだけです。これも、Reflogにきれいに明確に記録されます。
それでは、この「前」の状態のSHA-1ハッシュで始まる新しいブランチ(「失われた」ブランチの名前)を作成して、これを試してみましょう。
$ git branch feature/login 776f8ca
そして出来上がり! 一見失われたブランチが復元されたことを嬉しく思います。
「Tower」のようなGitデスクトップGUIを使用している場合は、便利なショートカットを使用できます。キーボードのCMD + Zを押すだけで、最後のコマンドを元に戻すことができます。ブランチを激しく削除した場合でも同様です。
コミットを別のブランチに移動する
多くのチームでは、 main
やdevelop
などの長期実行ブランチにコミットしないという合意があります。これらのブランチは、統合(マージやリベースなど)を通じてのみ新しいコミットを受け取る必要があります。 それでも、もちろん、間違いは避けられません。それでも、これらのブランチを忘れてコミットすることがあります。 では、どうすれば私たちが作った混乱を片付けることができますか?
幸いなことに、これらのタイプの問題は簡単に修正できます。 袖をまくって仕事に取り掛かりましょう。
最初のステップは、正しい宛先ブランチに切り替えてから、 cherry-pick
コマンドを使用してコミットを移動することです。
$ git checkout feature/login $ git cherry-pick 776f8caf
これで、最初の場所にあるはずの目的のブランチにコミットができます。 素晴らしい!
しかし、まだやるべきことが1つ残っています。それは、最初に誤って着陸したブランチをクリーンアップする必要があるということです。 cherry-pick
コマンドは、いわば、コミットのコピーを作成しました—しかし、オリジナルはまだ私たちの長期的なブランチに存在しています:
これは、実行時間の長いブランチに切り替えて、 git reset
を使用して削除する必要があることを意味します。
$ git checkout main $ git reset --hard HEAD~1
ご覧のとおり、ここではgit reset
コマンドを使用して誤ったコミットを消去しています。 HEAD~1
パラメーターは、Gitに「HEADの後ろに1リビジョン戻る」ように指示し、そのブランチの履歴から最上位の(この場合は不要な)コミットを効果的に消去します。
そして出来上がり:コミットはそもそも本来あるべき場所にあり、私たちの長期にわたるブランチはクリーンです—まるで私たちのミスが決して起こらなかったかのように!
古いコミットのメッセージの編集
タイプミスをコミットメッセージに密輸するのは非常に簡単です—そしてそれを発見するのはずっと後でです。 このような場合、 git commit
の古き--amend
オプションを使用してこの問題を修正することはできません。これは、最後のコミットでのみ機能するためです。 それより古いコミットを修正するには、「インタラクティブリベース」と呼ばれるGitツールを使用する必要があります。
まず、コミット履歴のどの部分を編集するかをInteractiveRebaseに指示する必要があります。 これは、コミットハッシュ(操作したいものの親コミット)をフィードすることによって行われます。
$ git rebase -i 6bcf266b
エディターウィンドウが開きます。 これには、コマンドでInteractiveRebaseの基礎として提供したコミット以降のすべてのコミットのリストが含まれています。
ここでは、最初の衝動に従わないことが重要です。このステップでは、まだコミットメッセージを編集していません。 代わりに、どのコミットでどのような操作を行いたいかをGitに伝えるだけです。 非常に便利なことに、このウィンドウの下部にあるコメントにアクションキーワードのリストがあります。 この場合、行#1をreword
でマークアップします(これにより、標準のpick
が置き換えられます)。
このステップであとは、エディターウィンドウを保存して閉じるだけです。 代わりに、マークアップしたコミットの現在のメッセージを含む新しいエディターウィンドウが開きます。 そして今がついに私たちの編集を行う時です!
プロセス全体を一目で確認できます。
壊れたコミットの修正(非常にエレガントな方法で)
最後に、ツールを元に戻すスイスアーミーナイフであるfixup
について見ていきます。 簡単に言えば、事後に壊れた/不完全な/間違ったコミットを修正することができます。 これは、2つの理由から本当に素晴らしいツールです。
- 問題が何であるかは問題ではありません。
ファイルを追加するのを忘れた、何かを削除した、間違った変更を加えた、または単にタイプミスをした可能性があります。fixup
はこれらすべての状況で機能します! - とてもエレガントです。
コミットのバグに対する私たちの通常の本能的な反応は、問題を修正する新しいコミットを生成することです。 この作業方法は、直感的に見えるかもしれませんが、コミット履歴が非常に混沌としているように見えます。 「元の」コミットがあり、次にこれらの小さな「バンドエイド」コミットがあり、元のコミットで失敗したことを修正します。 あなたの歴史には、コードベースで何が起こったのかを理解するのを難しくする、小さくて意味のないバンドエイドのコミットが散らばっています。
これが修正の出番です。それでも、この修正バンドfixup
をコミットすることができます。 しかし、ここに魔法があります。それは、元の壊れたコミットに適用され(そのように修復され)、醜いバンドエイドのコミットを完全に破棄します。
一緒に実例を見ていきましょう! ここで選択したコミットが壊れているとしましょう。
また、問題を解決するために、 error.html
という名前のファイルに変更を加えたとしましょう。 これが私たちがする必要がある最初のステップです:
$ git add error.html $ git commit --fixup 2b504bee
新しいコミットを作成していますが、これは特別なものであるとGitに伝えています。これは、指定されたSHA-1ハッシュ(この場合は2b504bee
)を使用した古いコミットの修正です。
2番目のステップは、Interactive Rebaseセッションを開始することです。これは、 fixup
がInteractiveRebaseの大きなツールセットに属しているためです。
$ git rebase -i --autosquash 0023cddd
このコマンドについて説明する価値があるのは2つです。 まず、なぜここでリビジョンハッシュとして0023cddd
を提供したのですか? 壊れた仲間の親コミットでインタラクティブリベースセッションを開始する必要があるためです。
次に、 --autosquash
オプションは何のためにありますか? それは私たちの肩から多くの仕事を取ります! 現在開いているエディタウィンドウでは、すべてがすでに準備されています。
--autosquash
オプションのおかげで、Gitはすでに私たちのために重労働を行っています:
- それは、
fixup
アクションキーワードで私たちの小さなバンドエイドコミットをマークしました。 そうすれば、Gitはそれをすぐ上のコミットと組み合わせてから破棄します。 - また、それに応じて行を並べ替え、修正したいコミットのすぐ下にバンドエイドコミットを移動しました(ここでも、修正はマークアップされたコミットを上のコミットと
fixup
ことで機能します!)。
つまり、ウィンドウを閉じる以外に何もすることはありません。
最終結果を最後に見てみましょう。
- 以前は壊れていたコミットが修正されました。バンドエイドのコミットで準備した変更が含まれるようになりました。
- 醜いバンドエイドのコミット自体は破棄されました。コミット履歴はクリーンで読みやすく、まるで間違いがまったく発生していないかのようです。
間違いを元に戻す方法を知ることは超大国です
おめでとう! これで、多くの困難な状況で首を救うことができます! これらの状況を本当に回避することはできません。開発者としての経験がどれほどあっても、間違いは仕事の一部にすぎません。 しかし、あなたはそれらに対処する方法を知ったので、あなたはのんびりとした心拍数でそれらに直面することができます。
Gitでの間違いを元に戻す方法について詳しく知りたい場合は、このトピックに関する一連の短いビデオである無料の「First AidKitforGit」をお勧めします。
間違いを楽しんでください—そしてもちろん、簡単に元に戻すことができます!