1. ホーム
  2. git

[解決済み] わかりやすく言うと、「git reset」は何をするものなのでしょうか?

2022-03-14 12:16:11

質問

私が見たのは 面白い記事 についての微妙な違いを説明しています。 git reset .

残念ながら、読めば読むほど、私が完全に理解していないように見えるのです。私はSVN出身ですが、Gitはまったく新しいパラダイムです。mercurialは簡単に理解できましたが、Gitはもっと技術的なんです。

私が思うに git reset が近いです。 hg revert ということですが、どうやら違いがあるようです。

では、具体的にどのような git reset を行うのですか?について、詳しい説明を入れてください。

  • オプション --hard , --soft--merge ;
  • で使用する奇妙な記法は HEAD というように HEAD^HEAD~1 ;
  • 具体的なユースケースとワークフロー。
  • 作業コピーの結果 HEAD と、あなたのグローバルなストレスレベル。

解決方法は?

一般的には git reset の機能は、現在のブランチをリセットして別の場所を指すようにし、場合によってはインデックスと作業ツリーを一緒に持ってくることです。具体的には、master ブランチ (現在チェックアウトされている) がこのような状態だとすると、次のようになります。

- A - B - C (HEAD, master)

で、master が C ではなく B を指すようにしたい場合、次のようにします。 git reset B で移動させます。

- A - B (HEAD, master)      # - C is still here, but there's no branch pointing to it anymore

余談ですが これはチェックアウトとは違います。もしあなたが git checkout B ということになります。

- A - B (HEAD) - C (master)

デタッチドHEADの状態で終了していますね。 HEAD 作業ツリー、インデックスがすべて一致 B で、master ブランチが取り残されています。 C . 新しいコミットを行う場合 D この時点で、おそらくあなたが望むものではない、次のようなものが得られます。

- A - B - C (master)
       \
        D (HEAD)

リセットがコミットを行うのではなく、ブランチ (コミットへのポインタ) を更新して別のコミットを指すようにするだけであることに注意しましょう。あとは、インデックスと作業ツリーに何が起こるかの詳細だけです。

使用例

の主なユースケースを多く取り上げています。 git reset 次のセクションのさまざまなオプションの説明の中にあります。ブランチ、インデックス、ワークツリーをリセットして、あるコミットを指すようにするのが共通点です。

注意すべきこと

  • --hard は、本当に仕事を失う原因になりかねません。ワークツリーを修正してしまうのです。

  • git reset [options] commit は、(一種の) コミットロスを引き起こす可能性があります。上のおもちゃの例では、コミット C . これはまだレポに残っていて、次の場所で見つけることができます。 git reflog show HEAD または git reflog show master しかし、実際にはもうどのブランチからもアクセスできないのです。

  • Git は 30 日後にそのようなコミットを永久に削除しますが、それまでは再びブランチを指して C を回復することができます ( git checkout C; git branch <new branch name> ).

引数

マニュアルによると、最も一般的な使い方は次のようなものです。 git reset [<commit>] [paths...] これは、与えられたパスを与えられたコミットからの状態にリセットします。パスが提供されない場合、ツリー全体がリセットされ、コミットが提供されない場合、それは HEAD(現在のコミット)であるとみなされます。これは git コマンドに共通するパターンなので(正確な意味は異なりますが、checkout、diff、log など)、それほど驚くことではありません。

例えば git reset other-branch path/to/foo は、path/to/foo にあるすべてのものを other-branch の状態にリセットします。 git reset -- . はカレントディレクトリを HEAD の状態にリセットし、単純な git reset は、すべてをHEADの状態にリセットします。

メインワークツリーとインデックスオプション

リセット中にワークツリーとインデックスに何が起こるかを制御するための4つの主要なオプションがあります。

インデックスとは、git の「ステージング・エリア」であり、次のような場合に使用されます。 git add をコミットするための準備として使用します。

  • --hard は、すべてをあなたがリセットしたコミットに一致させます。これはおそらく最も理解しやすいものです。ローカルで行ったすべての変更が取り込まれます。主な用途のひとつは、コミットを切り替えずに自分の作業を吹き飛ばすことです。 git reset --hard というのは git reset --hard HEAD つまり、ブランチは変更しないが、ローカルでの変更はすべて取り除くということです。もうひとつは、単にブランチをある場所から別の場所に移動し、インデックスとワークツリーを同期させたままにしておくものです。 これは、ワークツリーを変更するため、本当に仕事ができなくなる可能性があるものです。 を実行する前に、ローカルの仕事を捨てたいことをよくよく確認してください。 reset --hard .

  • --mixed はデフォルト、つまり git reset というのは git reset --mixed . これはインデックスをリセットしますが、作業ツリーはリセットしません。これは、すべてのファイルが無傷であることを意味します。しかし、元のコミットとリセットしたコミットの間に何らかの違いがあると、ローカルの変更 (あるいは追跡されていないファイル) として git ステータスに表示されます。この方法は、まずいコミットをしたことに気づいたけれども、それを修正して再コミットするためにすべての作業を残しておきたい場合に使用します。コミットするためには、ファイルを再度インデックスに追加しなければなりません ( git add ... ).

  • --soft インデックスに触れない または の作業ツリーです。の場合と同様に、すべてのファイルは無傷です。 --mixed として表示されますが、すべての変更は changes to be committed を、git ステータス (コミット準備のためのチェックイン) で指定します。これは、間違ったコミットをしたことに気づいたけれども作業はすべて順調で、あとは別の方法で再コミットするだけという場合に使用します。インデックスには何も手をつけていないので、必要ならすぐにコミットすることができます。

  • --merge は最近追加されたもので、失敗したマージを中止するのに役立つことを目的としています。これが必要な理由は git merge は、ダーティな作業ツリー (ローカルに変更を加えたもの) であっても、その変更がマージの影響を受けないファイルであれば、実際にマージを試行することを許可します。 git reset --merge はインデックスをリセットします( --mixed - はローカルでの変更として表示されます)、そしてマージの影響を受けたファイルをリセットし、他のファイルはそのままにしておきます。これでうまくいけば、悪いマージの前にあった状態にすべてを戻すことができます。通常は次のように使用します。 git reset --merge (意味 git reset --merge HEAD というのも、実際にブランチを移動させるのではなく、マージをリセットしたいだけだからです。( HEAD は、マージが失敗したため、まだ更新されていません)

    もう少し具体的に説明すると、ファイル A と B を変更し、ファイル C と D を変更したブランチでマージしようとしたとき、何らかの理由でマージに失敗し、それを中断することにしたとします。そこであなたは git reset --merge . CとDを元の状態に戻します。 HEAD しかし、A と B に対する修正は、マージの対象外であるため、そのままにしておきます。

もっと知りたい?

私はこう思う man git reset しかし、それらを本当に理解するためには、gitの動作に関するちょっとしたセンスが必要かもしれません。特に、時間をかけて注意深く読めば、様々なオプションやケースについて、インデックスや作業ツリーにおけるファイルの状態を詳細に示す表は、とても役に立ちます。(しかし、そうです、これらは非常に密です。彼らは非常に多くの上記の情報を非常に簡潔な形で伝えているのです)。

変な表記

奇妙な表記法" ( HEAD^HEAD~1 のようなハッシュ名を使わなくても、コミットを指定できるようにするための単なる省略記法です。 3ebe3f6 . これは リビジョンの指定"セクション のマニュアルページには、たくさんの例と関連する構文が掲載されています。キャレットとチルダは、実際には次のような意味です。 異なるもの :

  • HEAD~ の略です。 HEAD~1 で、コミットの最初の親を意味します。 HEAD~2 は、コミットの最初の親の最初の親を意味します。次のように考えてください。 HEAD~n は、"HEAD" よりも前の n コミット、または "HEAD" の第 n 世代の祖先である、と考えてください。
  • HEAD^ (または HEAD^1 ) は、コミットの最初の親を意味することもあります。 HEAD^2 はコミットの 第二 の親になります。通常のマージコミットは2つの親を持つことを覚えておいてください。最初の親はマージされるコミットで、2番目の親はマージされたコミットです。一般に、マージは実際には任意の数の親を持つことができます (オクトパスマージ)。
  • ^~ のように、演算子をつなげることができます。 HEAD~3^2 の3代目先祖の2代目親である。 HEAD , HEAD^^2 の最初の親の2番目の親は HEAD あるいは HEAD^^^ と等価である。 HEAD~3 .