git commitを削除しても変更は保持できますか


1057

開発ブランチの1つで、コードベースにいくつかの変更を加えました。作業中の機能を完了する前に、現在のブランチをマスターに切り替えて、いくつかの機能をデモする必要がありました。しかし、「git checkout master」を使用するだけで、開発ブランチで行った変更も保持され、masterの一部の機能が破壊されました。したがって、私が行ったのは、「一時的なコミット」というコミットメッセージを使用して開発ブランチの変更をコミットしてから、デモのマスターをチェックアウトすることでした。

デモが終了し、開発ブランチでの作業に戻ったので、行った変更を保持しながら、行った「一時的なコミット」を削除したいと思います。それは可能ですか?



51
@MattBall、必ずしもそうではありません。一方でgit stash優れたツールである、「作業中」のスローアウェイコミットは、あまりにも、非常に正当なデバイスです。
kostix

3
これはGithubからの素晴らしいリソースの海峡です:Gitで(ほとんど)何でも元に戻す方法
jasonleonhard

9
@MattBall @kostixええ、スタッシュは、リポジトリ全体の1つのグローバルスタックであることを考えると、「長期的な」スタッシングには特に適していません。ブランチで変更を隠しておき、他のブランチに移動し、他のことを何でも行い、その日のgit stashうちに他のブランチで使用していたのではないかと心配することなく戻ってきたいと思います。
アレック

4
注目に値することの1つstashは、それが完全にローカルであり、レポ削除またはレクリエーション、またはハードウェアの障害または損失によりコードが失われる傾向があることです。IMO、本当に短期間のWIPにのみ使用する必要があります。休日に行く前にWIPコミットが大好きです:P ..それをブレインダンプコミットと呼んでください!
ϹοδεMεδιϲ 2018

回答:


1619

それはこれと同じくらい簡単です:

git reset HEAD^

注:一部のシェル^は特殊文字として扱われるため(たとえば、一部のWindowsシェルまたはグロビングが有効になっているZSH)、その場合は引用符"HEAD^"囲む必要があります。

git resetなし、--hardまたはファイルを変更せずに、指定したコミットを指すように--soft移動しますHEADHEAD^現在のコミットの(最初の)親コミットを指します。これは、一時的なコミットの前のコミットです。

別のオプションは、通常どおり続行し、次に次のコミットポイントで実行することです。

git commit --amend [-m … etc]

代わりに最新のコミットを編集し、上記と同じ効果があります。

これは(ほとんどすべてのgitの回答と同様に)、他の誰かがプルした可能性のある場所に悪いコミットを既にプッシュしている場合に問題を引き起こす可能性があることに注意してください。それを避けてください


47
これは非常に単純ですが、すでにコミットをリモートにプッシュし、他の誰かがそれをプルした場合、私は謝罪以外のことをするのを非常にためらいます。
atw13 2013

11
@sicophrenic、この機会に"Reset Demystified"を読む機会をお見逃しなく。
kostix 2013

33
私はMore?これをした後に得ます。私はそのプロンプトで入力するものは何でも私に与えますfatal: ambiguous argument 'HEADwhateverItypedIn': unknown revision or path not in the working tree.
DaAwesomeP

50
@DaAwesomePは^、特殊文字として扱うシェルを使用しているように聞こえます。参照を引用するか、引用符で囲まない"HEAD^"代替構文を使用することができますHEAD~1
Gareth

8
私のために働いたが、キャラクターをエスケープしなければならなかったgit reset HEAD\^
cevaris

188

これを処理する方法は2つあります。どちらが簡単かは状況によって異なります

リセット

あなたが取り除きたいコミットが最後のコミットであり、あなたが単に使用できる追加の作業をしていない場合 git-reset

git reset HEAD^

現在のHEADの直前のコミットにブランチを戻します。ただし、実際には作業ツリー内のファイルは変更されません。その結果、そのコミットで行われた変更は変更されたものとして表示されます。これは「コミット解除」コマンドのようなものです。実際、私はそれを行うためのエイリアスを持っています。

git config --global alias.uncommit 'reset HEAD^'

その後git uncommit、将来的に1つのコミットをバックアップするために使用できます。

潰れ

コミットを押しつぶすとは、2つ以上のコミットを1つにまとめることを意味します。私はかなり頻繁にこれを行います。あなたの場合、あなたは半分完了した機能をコミットしていて、それを終えて、適切な永続的なコミットメッセージで再びコミットするでしょう。

git rebase -i <ref>

はっきり言っておきたいのは、これはいくつでもコミットできるということです。削除git logするコミットを実行して見つけ、そのSHA1をコピーして、の代わりに使用し<ref>ます。Gitはインタラクティブなリベースモードに移動します。それはあなたの現在の状態とあなたがの代わりに置いたものの間のすべてのコミットを表示します<ref>。つまり、<ref>10コミット前であれば、10コミットすべてが表示されます。

各コミットの前には、と表示されますpick。取り除きたいコミットを見つけ、それをpickからfixupまたはに変更しsquashます。使用してfixup簡単に破棄し、そのコミットメッセージを、リスト内のその直接の前身に変更をマージします。squashキーワードは、同じことをしていますが、新しく結合されたコミットのコミットメッセージを編集することができます。

エディターを終了すると、リストに表示された順序でコミットが再コミットされることに注意してください。したがって、一時的なコミットを行い、同じブランチで他の作業を行い、その後のコミットで機能を完了した場合、リベースを使用すると、コミットを再ソートしてそれらを押しつぶすことができます。

警告:

リベースにより履歴が変更されます-他の開発者とすでに共有しているコミットに対しては、これを行わないでください。

隠しておく

今後、この問題を回避するために、を使用git stashして、コミットされていない作業を一時的に保存することを検討してください。

git stash save 'some message'

これにより、現在の変更がスタッシュリストの横に保存されます。上記はstashコマンドの最も明示的なバージョンであり、コメントを付けて、何を隠しているかを説明できます。また、単に実行git stashして他には何もできませんが、メッセージは保存されません。

あなたはあなたの隠しリストを閲覧することができます...

git stash list

これにより、すべてのスタッシュ、それらが行われたブランチ、メッセージと各行の先頭、および次のようなstash@{#}スタッシュの識別子が表示されます。#はスタッシュの配列内の位置です。

stashを復元するには(stashが最初に作成された場所に関係なく、任意のブランチで実行できます)、単に実行します...

git stash apply stash@{#}

繰り返しますが、#はスタッシュの配列内の位置です。復元するスタッシュが適切な0位置にある場合-つまり、それが最新のスタッシュだった場合。次に、スタッシュ位置を指定せずにコマンドを実行するだけで、gitは最後のものを意味すると想定しますgit stash apply

したがって、たとえば、自分が間違ったブランチで作業していることがわかった場合、次の一連のコマンドを実行できます。

git stash
git checkout <correct_branch>
git stash apply

あなたの場合、ブランチをもう少し移動しましたが、同じ考え方がまだ当てはまります。

お役に立てれば。


6
git config --global alias.uncommit reset HEAD^エイリアスはリセットするためにコミットを解除します。代わりに、やるgit config --global alias.uncommit 'reset HEAD^'
mernst

3
Windowsコマンドプロンプトで使用する場合は、^ではなく^^を使用する必要があることに注意してください。
Pramod BR

106

あなたはこれを探していると思います

git reset --soft HEAD~1

ステージングへのコミットで行われた変更を保持しながら、最新のコミットを取り消します。


7
ありがとう。これでうまくいきました。git reset HEAD^Windowsで呼び出すと、「詳細」と表示されるだけです。-それが何を意味するか
タイロン

12
@Tyron ^はDOSのエスケープ文字です。新しい行と組み合わせると、前のコマンドの継続プロンプトとして機能します。タイピングgit reset HEAD^^はWindowsで機能するはずです。
trk

40

はい、変更を削除せずにコミットを削除できます:git reset @〜


7
これは私が本当に望んでいることであり、私の意見ではそれが受け入れられる答えになるでしょう。
Carlos Liu

2
興味深い、コンパクトな構文、私はこれまでに見たことも、使用したこともありません。どのようにそれは異なっていますgit reset --softgit reset --keep
user776686

18

git reset HEAD^ --softまたはを探していますgit reset HEAD^ --mixed

ドキュメントに記載されているように、resetコマンドには3つのモードがあります。

git reset HEAD^ --soft

元に戻すgit commit。変更は作業ツリー(プロジェクトフォルダー)+インデックス(--cached)にまだ存在します

git reset HEAD^ --mixed

元に戻すgit commit+ git add。作業ツリーにはまだ変更が存在します

git reset HEAD^ --hard

あなたがコードベースにこれらの変更を加えたことがないように。変更は作業ツリーから削除されます。


9

zshを使用している場合は、以下を使用する必要があります。

git reset --soft HEAD\^

ここで説明:https : //github.com/robbyrussell/oh-my-zsh/issues/449

URLが機能しなくなった場合の重要な部分は次のとおりです。

コマンドで^をエスケープします

代わりにHEAD〜を使用して、毎回エスケープする必要がないようにすることもできます。


15
私は、このコマンドを覚えていないし、これをGoogleと私自身の回答ハハハハを見つけなければならないことができます
グレッグHilston

2
git reset HEAD^私のためにzshで働いていますが、修正されている可能性があります。
Ben Kolya Mansley

@BenKolyaMansley実行しているzshのバージョンを教えてください。
グレッグヒルストン

私が使用していますzsh 5.3 (x86_64-apple-darwin18.0)
Ben Kolya Mansley

7

私の場合、すでにレポにプッシュしています。痛い!

次のようにすることで、ローカルファイルの変更を維持しながら、特定のコミットを元に戻すことができます。

git revert -n <sha>

このようにして、必要な変更を保持し、すでにプッシュされたコミットを元に戻すことができました。


私の場合、リモートリポジトリに既にプッシュしたものを元に戻す必要がありました。さらに痛い!最良の方法はgit revert bad-commit-sha、それから、そしてgit revert -n revert-commit-just-created-shaそこから修理することでした。あなたは私を途中で手に入れた。ありがとう!
TinkerTenorSoftwareGuy 2017

これは反対のことをするようです、いいえ?選択したコミットで行われた変更を元に戻すことに対応する新しい変更を作成します。これらの新しい変更をコミットすると、実際に保持したい作業が取り消されます。
2018

3

git 2.9(正確には2.9.2.windows.1)を使用 git reset HEAD^すると、さらにプロンプ​​トが表示されます。ここで期待される入力は不明です。下のスクリーンショットを参照してください

ここに画像の説明を入力してください

git reset HEAD~#numberOfCommits変更をそのままにしてリセットしたいローカルコミットの数を選択できる他のソリューションを見つけました。したがって、すべてのローカルコミットと限られた数のローカルコミットを破棄する機会を得ます。

git reset HEAD~1動作中のスクリーンショットを以下に示します。 ここに画像の説明を入力してください

ここに画像の説明を入力してください


おそらく^文字をエスケープする必要があります-git reset "HEAD ^"またはgit reset HEAD \ ^を試してください
Mark Fisher

これに加えて、git reset HEAD ^^は単一の^として機能し、新しい行として扱われます。
John Oss

2

それを行うもう1つの方法。

一時コミットの上部にコミットを追加してから、次のようにします。

git rebase -i

2つのコミットを1つにマージするには(コマンドは、明示的な指示を含むテキストファイルを開き、編集します)。


2
技術的には正確ですが、単純に行うほどエレガントではありませんgit reset HEAD^。Gitリベースには、ここでエラーが発生する余地がたくさんあります。
TheBuzzSaw

0

2020シンプルな方法:

git reset <commit_hash>

(保持したい最後のコミットのコミットハッシュ)。

コミットがプッシュされた場合は、次に行うことができます。

git push -f

コミットされていない変更をローカルに保持します

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.