Git
English ▾ トピック ▾ 最新バージョン ▾ git-reset は 2.39.3 で最後に更新されました

名前

git-reset - 現在のHEADを指定された状態にリセットする

概要

git reset [-q] [<tree-ish>] [--] <pathspec>…​
git reset [-q] [--pathspec-from-file=<file> [--pathspec-file-nul]] [<tree-ish>]
git reset (--patch | -p) [<tree-ish>] [--] [<pathspec>…​]
git reset [--soft | --mixed [-N] | --hard | --merge | --keep] [-q] [<commit>]

説明

最初の3つの形式では、<tree-ish> からインデックスにエントリをコピーします。最後の形式では、現在のブランチヘッド (HEAD) を <commit> に設定し、オプションでインデックスと作業ツリーを一致するように変更します。<tree-ish>/<commit> は、すべての形式でデフォルトで HEAD になります。

git reset [-q] [<tree-ish>] [--] <pathspec>…​
git reset [-q] [--pathspec-from-file=<file> [--pathspec-file-nul]] [<tree-ish>]

これらの形式は、<pathspec> に一致するすべてのパスのインデックスエントリを、<tree-ish> の状態にリセットします。(これは、作業ツリーや現在のブランチには影響しません。)

これは、git reset <pathspec>git add <pathspec> の反対であることを意味します。このコマンドは、git restore [--source=<tree-ish>] --staged <pathspec>... と同等です。

git reset <pathspec> を実行してインデックスエントリを更新した後、git-restore[1] を使用して、インデックスから作業ツリーにコンテンツをチェックアウトできます。または、git-restore[1] を使用し、--source でコミットを指定して、コミットからインデックスおよび作業ツリーにパスのコンテンツを一度にコピーできます。

git reset (--patch | -p) [<tree-ish>] [--] [<pathspec>…​]

インデックスと <tree-ish> (デフォルトは HEAD) の差分でチャンクをインタラクティブに選択します。選択されたチャンクは、インデックスに逆順に適用されます。

これは、git reset -pgit add -p の反対であること、つまり、チャンクを選択的にリセットするために使用できることを意味します。--patch モードの操作方法については、git-add[1] の「インタラクティブモード」セクションを参照してください。

git reset [<mode>] [<commit>]

この形式は、現在のブランチヘッドを <commit> にリセットし、場合によっては <mode> に応じてインデックス (<commit> のツリーにリセット) および作業ツリーを更新します。操作の前に、ORIG_HEAD が現在のブランチの先端に設定されます。<mode> が省略された場合は、デフォルトで --mixed になります。<mode> は次のいずれかである必要があります。

--soft

インデックスファイルまたは作業ツリーにはまったく触れません (ただし、すべてのモードが行うように、ヘッドを <commit> にリセットします)。これにより、すべての変更されたファイルは、git status で示されるように、「コミットされる変更」として残されます。

--mixed

インデックスはリセットしますが、作業ツリーはリセットしません (つまり、変更されたファイルは保持されますが、コミット対象としてはマークされません)。また、更新されなかったものが報告されます。これがデフォルトのアクションです。

-N が指定された場合、削除されたパスは、intent-to-add としてマークされます ( git-add[1] を参照)。

--hard

インデックスと作業ツリーをリセットします。<commit> 以降の作業ツリー内の追跡対象ファイルへの変更は破棄されます。追跡対象ファイルを書き込む際に妨げとなる、追跡対象外のファイルまたはディレクトリは単純に削除されます。

--merge

インデックスをリセットし、作業ツリー内のファイルを <commit>HEAD で異なるように更新しますが、インデックスと作業ツリーで異なるファイル (つまり、追加されていない変更があるファイル) は保持します。<commit> とインデックスで異なるファイルにステージされていない変更がある場合、リセットは中止されます。

言い換えれば、--mergegit read-tree -u -m <commit> のような処理を行いますが、マージされていないインデックスエントリを引き継ぎます。

--keep

インデックスエントリをリセットし、<commit>HEAD で異なる作業ツリー内のファイルを更新します。<commit>HEAD で異なるファイルにローカルな変更がある場合、リセットは中止されます。

--[no-]recurse-submodules

作業ツリーを更新するとき、--recurse-submodules を使用すると、スーパープロジェクトに記録されているコミットに従って、すべてのアクティブなサブモジュールの作業ツリーも再帰的にリセットされ、サブモジュールの HEAD もそのコミットで分離された状態に設定されます。

3つのコマンドの違いについては、git[1] の「リセット、復元、および元に戻す」を参照してください。

オプション

-q
--quiet

エラーのみを報告します。

--refresh
--no-refresh

mixed リセット後にインデックスを更新します。デフォルトで有効になっています。

--pathspec-from-file=<file>

Pathspec は、コマンドライン引数の代わりに <file> で渡されます。<file> が正確に - の場合は、標準入力が使用されます。Pathspec 要素は、LF または CR/LF で区切られます。Pathspec 要素は、構成変数 core.quotePath で説明されているように引用符で囲むことができます ( git-config[1] を参照)。--pathspec-file-nul およびグローバルな --literal-pathspecs も参照してください。

--pathspec-file-nul

--pathspec-from-file でのみ意味があります。Pathspec 要素は NUL 文字で区切られ、他のすべての文字は文字どおりに解釈されます (改行や引用符を含む)。

--

これ以上の引数をオプションとして解釈しないでください。

<pathspec>…​

操作の影響を受けるパスを制限します。

詳細については、gitglossary[7]pathspec エントリを参照してください。

add を取り消す
$ edit                                     (1)
$ git add frotz.c filfre.c
$ mailx                                    (2)
$ git reset                                (3)
$ git pull git://info.example.com/ nitfol  (4)
  1. あなたは何かを楽しく作業しており、これらのファイル内の変更が正常な順序になっていることがわかります。git diff を実行したときに、それらを表示したくありません。他のファイルや変更を作業する予定があり、これらのファイルによる作業は気が散るからです。

  2. 誰かがあなたにプルするように依頼し、その変更はマージする価値があるように聞こえます。

  3. ただし、すでにインデックスを汚してしまっています (つまり、インデックスが HEAD コミットと一致しません)。ただし、これから行うプルが frotz.c または filfre.c に影響しないことはわかっているため、これら2つのファイルのインデックス変更を元に戻します。作業ツリーの変更はそこに残ります。

  4. 次に、プルしてマージできます。frotz.c および filfre.c の変更は作業ツリーに残ります。

コミットを元に戻してやり直す
$ git commit ...
$ git reset --soft HEAD^      (1)
$ edit                        (2)
$ git commit -a -c ORIG_HEAD  (3)
  1. これは、コミットしたばかりのものが不完全であったり、コミットメッセージをスペルミスしたりした場合、またはその両方の場合に最も頻繁に行われます。「reset」前の状態に作業ツリーを残します。

  2. 作業ツリーファイルを修正します。

  3. "reset" は古いヘッドを .git/ORIG_HEAD にコピーします。ログメッセージから開始してコミットをやり直します。メッセージをさらに編集する必要がない場合は、代わりに -C オプションを指定できます。

    git-commit[1]--amend オプションも参照してください。

コミットを元に戻してトピックブランチにする
$ git branch topic/wip          (1)
$ git reset --hard HEAD~3       (2)
$ git switch topic/wip          (3)
  1. いくつかのコミットを作成しましたが、それらが master ブランチにあるのは時期尚早だと気づきました。トピックブランチでそれらの洗練を続けたいので、現在の HEAD から topic/wip ブランチを作成します。

  2. これらの3つのコミットを削除するために、master ブランチを巻き戻します。

  3. topic/wip ブランチに切り替えて作業を続けます。

コミットを完全に元に戻す
$ git commit ...
$ git reset --hard HEAD~3   (1)
  1. 最後の3つのコミット (HEADHEAD^、および HEAD~2) は悪く、二度と表示したくありません。これらのコミットを既に他の人に渡している場合は、これを 行わないでください。(そうすることの影響については、git-rebase[1] の「アップストリームのリベースからの復旧」セクションを参照してください。)

マージまたはプルを元に戻す
$ git pull                         (1)
Auto-merging nitfol
CONFLICT (content): Merge conflict in nitfol
Automatic merge failed; fix conflicts and then commit the result.
$ git reset --hard                 (2)
$ git pull . topic/branch          (3)
Updating from 41223... to 13134...
Fast-forward
$ git reset --hard ORIG_HEAD       (4)
  1. アップストリームからの更新を試みたところ、多くのコンフリクトが発生しました。今はマージに多くの時間を費やしたくないため、後で対応することにしました。

  2. "pull" はマージコミットを作成しなかったため、git reset --hardgit reset --hard HEAD の同義語)は、インデックスファイルとワーキングツリーの混乱を解消します。

  3. トピックブランチを現在のブランチにマージしたところ、fast-forward になりました。

  4. しかし、トピックブランチはまだ公開する準備ができていないと判断しました。"pull" や "merge" は常に現在のブランチの元の先端を ORIG_HEAD に残すため、そこにハードリセットすると、インデックスファイルとワーキングツリーがその状態に戻り、ブランチの先端がそのコミットにリセットされます。

ダーティなワーキングツリー内でのマージまたはプルを取り消す
$ git pull                         (1)
Auto-merging nitfol
Merge made by recursive.
 nitfol                |   20 +++++----
 ...
$ git reset --merge ORIG_HEAD      (2)
  1. ワーキングツリーにローカルな変更がある場合でも、他のブランチの変更がローカルな変更と重複しないことがわかっている場合は、安全に git pull を実行できます。

  2. マージの結果を確認した後、他のブランチの変更が不満な場合もあります。git reset --hard ORIG_HEAD を実行すると、元の状態に戻りますが、ローカルな変更は破棄されます。これは望ましくありません。git reset --merge はローカルな変更を保持します。

中断されたワークフロー

大規模な変更作業中に、緊急の修正リクエストによって作業が中断されたとします。ワーキングツリー内のファイルはまだコミットできる状態ではありませんが、クイックなバグ修正のために他のブランチに移動する必要があります。

$ git switch feature  ;# you were working in "feature" branch and
$ work work work      ;# got interrupted
$ git commit -a -m "snapshot WIP"                 (1)
$ git switch master
$ fix fix fix
$ git commit ;# commit with real log
$ git switch feature
$ git reset --soft HEAD^ ;# go back to WIP state  (2)
$ git reset                                       (3)
  1. このコミットは破棄されるため、使い捨てのログメッセージで構いません。

  2. これにより、コミット履歴から *WIP* コミットが削除され、ワーキングツリーがそのスナップショットを作成する直前の状態に設定されます。

  3. この時点では、インデックスファイルには *snapshot WIP* としてコミットしたすべての WIP の変更が残っています。これにより、インデックスが更新され、WIP ファイルがコミットされていないものとして表示されます。

    git-stash[1] も参照してください。

インデックス内の単一ファイルをリセットする

ファイルをインデックスに追加したが、後でコミットに追加したくないと判断したとします。git reset を使用すると、変更を保持したままインデックスからファイルを削除できます。

$ git reset -- frotz.c                      (1)
$ git commit -m "Commit files in index"     (2)
$ git add frotz.c                           (3)
  1. これにより、ワーキングディレクトリに残したまま、インデックスからファイルが削除されます。

  2. これにより、インデックス内の他のすべての変更がコミットされます。

  3. ファイルを再度インデックスに追加します。

いくつかの以前のコミットを破棄しながら、ワーキングツリーの変更を保持する

作業中のものをコミットし、その後少し作業を続けたとします。しかし、ワーキングツリーの内容は以前にコミットしたものとは関係のない別のブランチにあるべきだと考えます。新しいブランチを開始し、ワーキングツリーの変更を保持しながらリセットできます。

$ git tag start
$ git switch -c branch1
$ edit
$ git commit ...                            (1)
$ edit
$ git switch -c branch2                     (2)
$ git reset --keep start                    (3)
  1. これにより、branch1 に最初の編集がコミットされます。

  2. 理想的な世界では、branch2 を作成して切り替えたとき (つまり、git switch -c branch2 start) に、以前のコミットが新しいトピックに属していないことに気付いた可能性がありますが、完璧な人はいません。

  3. ただし、reset --keep を使用して、branch2 に切り替えた後に不要なコミットを削除できます。

コミットを複数のコミットに分割する

論理的に分離された多くの変更を作成し、それらをまとめてコミットしたとします。その後、各論理チャンクを独自のコミットに関連付けた方が良いと判断します。git reset を使用して、ローカルファイルの内容を変更せずに履歴を巻き戻し、次に git add -p を連続して使用して、どのチャンクを各コミットに含めるかを対話形式で選択し、git commit -c を使用してコミットメッセージを事前に入力できます。

$ git reset -N HEAD^                        (1)
$ git add -p                                (2)
$ git diff --cached                         (3)
$ git commit -c HEAD@{1}                    (4)
...                                         (5)
$ git add ...                               (6)
$ git diff --cached                         (7)
$ git commit ...                            (8)
  1. まず、履歴を1つ前のコミットに戻して元のコミットを削除しますが、ワーキングツリーにはすべての変更が残るようにします。-N を指定すると、HEAD で追加された新しいファイルは、git add -p で見つけられるようにマークされたままになります。

  2. 次に、git add -p 機能を使用して、追加する diff チャンクを対話形式で選択します。これにより、diff チャンクごとに順に質問され、「はい、これを含める」、「いいえ、これを含めない」、または非常に強力な「編集」などの簡単なコマンドを使用できます。

  3. 含めるチャンクに満足したら、git diff --cached を使用して、最初のコミット用に準備されたものを確認する必要があります。これにより、インデックスに移動され、コミットされようとしているすべての変更が表示されます。

  4. 次に、インデックスに保存された変更をコミットします。-c オプションは、最初のコミットで開始した元のメッセージからコミットメッセージを事前に入力するように指定します。これは、再入力する手間を省くのに役立ちます。HEAD@{1} は、元のリセットコミットの前の (1回前の変更) HEAD があったコミットの特別な表記法です。詳細については、git-reflog[1] を参照してください。他の有効なコミット参照を使用することもできます。

  5. 手順 2~4 を複数回繰り返して、元のコードを任意の数のコミットに分割できます。

  6. これで、多くの変更が独自のコミットに分割され、git add のパッチモードを使用しなくなり、残りのコミットされていない変更をすべて選択できるようになる可能性があります。

  7. もう一度、含めるものを確認してください。また、git diff で、後でコミットされる変更が残っていないことも確認することをお勧めします。

  8. 最後に、最後のコミットを作成します。

議論

以下の表は、実行時に何が起こるかを示しています。

git reset --option target

ファイルのステータスに応じて、異なるリセットオプションで HEAD を別のコミット (target) にリセットします。

これらの表では、ABC、および D は、ファイルのいくつかの異なるステータスです。たとえば、最初の表の最初の行は、ワーキングツリー内のファイルがステータス A、インデックス内のステータスが BHEAD 内のステータスが C、ターゲット内のステータスが D の場合、git reset --soft target はワーキングツリー内のファイルをステータス A のままにし、インデックスをステータス B にします。HEAD (現在のブランチの先端、ブランチ上にいる場合) を target (ファイルがステータス D になっている) にリセット (つまり、移動) します。

working index HEAD target         working index HEAD
----------------------------------------------------
 A       B     C    D     --soft   A       B     D
			  --mixed  A       D     D
			  --hard   D       D     D
			  --merge (disallowed)
			  --keep  (disallowed)
working index HEAD target         working index HEAD
----------------------------------------------------
 A       B     C    C     --soft   A       B     C
			  --mixed  A       C     C
			  --hard   C       C     C
			  --merge (disallowed)
			  --keep   A       C     C
working index HEAD target         working index HEAD
----------------------------------------------------
 B       B     C    D     --soft   B       B     D
			  --mixed  B       D     D
			  --hard   D       D     D
			  --merge  D       D     D
			  --keep  (disallowed)
working index HEAD target         working index HEAD
----------------------------------------------------
 B       B     C    C     --soft   B       B     C
			  --mixed  B       C     C
			  --hard   C       C     C
			  --merge  C       C     C
			  --keep   B       C     C
working index HEAD target         working index HEAD
----------------------------------------------------
 B       C     C    D     --soft   B       C     D
			  --mixed  B       D     D
			  --hard   D       D     D
			  --merge (disallowed)
			  --keep  (disallowed)
working index HEAD target         working index HEAD
----------------------------------------------------
 B       C     C    C     --soft   B       C     C
			  --mixed  B       C     C
			  --hard   C       C     C
			  --merge  B       C     C
			  --keep   B       C     C

reset --merge は、コンフリクトが発生したマージからリセットするときに使用することを目的としています。マージ操作では、マージに関係するワーキングツリーファイルが開始前にインデックスに対してローカルな変更がないこと、および結果をワーキングツリーに書き出すことが保証されます。したがって、インデックスとターゲットの間、およびインデックスとワーキングツリーの間に何らかの差異が見られる場合、それはコンフリクトが発生して失敗した後にマージ操作が残した状態からリセットしていないことを意味します。そのため、この場合は --merge オプションを許可しません。

reset --keep は、ワーキングツリーの変更を保持しながら、現在のブランチの最後のコミットの一部を削除する場合に使用することを目的としています。削除したいコミットの変更と保持したいワーキングツリーの変更の間でコンフリクトが発生する可能性がある場合は、リセットは許可されません。そのため、ワーキングツリーと HEAD の間、および HEAD とターゲットの間に変更がある場合は許可されません。安全のため、マージされていないエントリがある場合も許可されません。

次の表は、マージされていないエントリがある場合に何が起こるかを示しています。

working index HEAD target         working index HEAD
----------------------------------------------------
 X       U     A    B     --soft  (disallowed)
			  --mixed  X       B     B
			  --hard   B       B     B
			  --merge  B       B     B
			  --keep  (disallowed)
working index HEAD target         working index HEAD
----------------------------------------------------
 X       U     A    A     --soft  (disallowed)
			  --mixed  X       A     A
			  --hard   A       A     A
			  --merge  A       A     A
			  --keep  (disallowed)

X は任意の状態を意味し、U はマージされていないインデックスを意味します。

GIT

git[1] スイートの一部

scroll-to-top