Gitでの変更とコミットの取り消し


取り消す必要があることは常に発生します。意図しない編集を入力した、修正しようとしたら状況が悪化した、または誰にも見られたくないコミットをしてしまった。Gitはあなたのプロジェクトの過去のほぼすべてのバージョンの記録を保持しているため、ほとんどのミスは一瞬感じるより復旧可能です。どのツールを使うかは、ミスがどこまで進んでいるかによります: まだエディタに入ったままか、既にステージングされているか、既にコミットされているか、または既にチームメイトが見られる場所にプッシュされているか。この章ではそれぞれの段階を順番に説明します。
pushとpullとは?
Pushはあなたのコミットをチームメイトも作業する共有リポジトリのコピーに送信し、Pullは彼らのコミットをあなたに持ってきます。Remotes and GitHubは両方について完全に説明しています。この章では「プッシュされた」はコミットがあなたのマシンを離れたことを意味します。
コミット前に変更を破棄する
コミットループのweather-appでstyles.cssのスタイルを変更中だとします。新しいレイアウトは悪い考えだとわかりました。ステージングしていない、コミットもしていない。ファイルを前の状態に戻すだけ。その仕事にはgit restoreがちょうど良いです:
$ git status
On branch main
Changes not staged for commit:
modified: styles.css
$ git restore styles.css
$ git status
On branch main
nothing to commit, working tree cleangit restore <file>はコミットされていない編集を破棄し、ファイルを最後に保存された状態に戻します。git addでファイルを既にステージングしていた場合、ファイルがワーキングディレクトリではなくステージング領域に座っているため、素のgit restoreは変更しません。まずアンステージングしてからリストアします:
$ git add styles.css
$ git restore --staged styles.css
$ git restore styles.css2つの領域に対して2つの分離した移動: git restore --stagedはファイルをステージング領域から戻し、単独のgit restoreはワーキングディレクトリの編集を破棄します。git restoreはコミットされていない作業のみを対象にします。変更がコミットされると、別のコマンドが引き継ぎます。
git restore <file>はコミットしていない編集を破棄し、ファイルを前の状態に戻します。既にgit addで変更をステージングしていた場合、まずgit restore --staged <file>でアンステージングし、編集を消したければファイルをリストアしてください。これはコミットしていない変更でのみ機能するため、既に保存したミスを救うことはできません。 git stashで作業を一時保存する
時々修正するミスではなく、ただタイミングが悪いだけです。styles.cssの編集途中で、チームメイトがあなたに別のブランチで必要とし、半完成のスタイルをコミットする準備ができていません。git stashは変更を一時保存し、きれいなワーキングディレクトリをあなたに与えるため、離れて後で戻ることができます。
$ git status
On branch main
Changes not staged for commit:
modified: styles.css
$ git stash
Saved working directory and index state WIP on main: 8f3c7d1 Cache forecast responses in localStorage
$ git status
On branch main
nothing to commit, working tree cleanstyles.cssへの編集は消えていません。駐車されています。準備ができたらgit stash popで戻してください:
$ git stash pop
On branch main
Changes not staged for commit:
modified: styles.cssgit stashはまだコミットする準備ができていない変更用で、ブランチにコミットを作成することはありません。
git stashはコミットする準備ができていない変更を一時保存するため、ワーキングディレクトリがきれいになり、git stash popで後で戻ります。何もコミットされず、何も失われません。編集は少し駐車されています。チームメイトが今別のブランチで必要な場合、私はこれを常に使用します。 git revertでコミットを取り消す
コミット8f3c7d1「Cache forecast responses in localStorage」が間違っていることが判明し、既にプッシュされているため、チームメイトも引っ張られています。そのコミットを書き直すことは、既に誰か他の人が持っているものを変更することを意味し、彼らのコピーと次にプルするときにあなたのコピーが一致しません。git revertは既に存在するものを何も変更せずにこれを解決します。反対の変更を適用する全く新しいコミットを作成します。
$ git revert 8f3c7d1
[main 2b6f0d1] Revert "Cache forecast responses in localStorage"履歴は元のコミットとそれを取り消すコミットの両方を順番に示しています。誰のコピーも再形成する必要がなく、チームメイトは他のコミット同様新しいrevertコミットをプルします。
git revertは他の人が既に持つコミットで常に安全です。古いコミットを変更する代わりに新しいコミットを追加するからです。
git revert <commit>は元のコミットを消すのではなく、それを逆転させる全く新しいコミットを追加することでコミットを取り消します。そのためコミットが既に他の誰かと共有されている場合、既に保存されたものが何も変更されないため、安全な選択肢です。履歴はミスと修正の両方の記録を保持します。Gitを長く使うほどそれを好みます。 git resetで巻き戻す: soft、mixed、hard
コミットを取り消す3番目の方法があります。git resetです。revertとは異なる動作をします: 古いコミットを取り消す新しいコミットを追加する代わりに、resetは現在のブランチを完全に異なるコミットを指すように移動します。それは誰も見ていないコミットに対して高速でクリーンにし、見た人のコミットに対しては危険です。
Resetはrestoreとrevertの上の、より広く使用して誤った従兄弟です。ほとんどの日々の修正ではそれを必要としません。restore、revert、stashは「助けて、これを取り消して」という瞬間の大部分をカバーします。他の人の説明にはそれを見るでしょう。そのため見出しは: resetはあなたのブランチを履歴を遡ります。そのモード1つ--hardはコミットされていない作業を確認なしで破棄します。あなたがどこかからコピーするコマンドにgit reset --hardが含まれる場合、実行する前に何をするかを読んでください。
git resetに到達しません。restore、revert、stashはほぼすべてをカバーします。それでも、それの形を知ってください: resetはブランチを前のコミットに戻し、--hardモードはワーキングディレクトリを確認なしで消去します。reset --hardを含むコマンドをコピーして実行する場合は、実際の注意で扱ってください。 revertまたはresetを選択する
どのツールに到達するかを決める規則: 他の誰かが既にこのコミットをプルしていますか?はい、revert。コミットがあなたのマシンにのみ存在し、プッシュしなかったブランチ上の場合、resetは良好であり、しばしばより整然とした修正です。確実でない場合、revertは常に安全な選択肢です。両方のケースで機能するからです。
git reflogで失われたコミットを復旧する
reset --hard、乱雑なリベース、またはブランチを誤って削除することは、コミットが完全に消えたように見える可能性があります。通常消えていません。GitはHEADとブランチが指した場所のローカル記録を保持し、**reflog**と呼ばれ、そのログはほぼ常に失われたように見えるコミットに戻るあなたの方法です。
あなたはこれをしばしば必要とするのは間違いありませんが、ここは見出しです: Gitは消えたように見えた瞬間にほぼ何も破棄しません。reset --hardを実行してその後そのコミットが必要であることに気づいた場合、非常に可能性の高い方法があります。もっと深く掘り下げる準備ができています。ここでカバーされています。
reset --hardを実行して後でそのコミットが必要であることに気づいた場合、それはおそらくまだ復旧可能です。Gitはあなたの作業が指した場所のローカル記録を保持し、reflowと呼ばれ、それはおそらく消えたように見えるコミットを戻すのに十分です。これはディープダイブテリトリーですが、それがそこにあることを知っていることは心強いです。 
