web-dev-qa-db-ja.com

追加されたファイルのみをどのように隠しますか?

たとえば、git statusは次のようになります。

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   app/src/[....]
    modified:   app/src/[....]
    new file:   app/src/[....]
    deleted:    app/src/[....]
    modified:   app/src/[....]
    modified:   test/unit/[....]
    modified:   test/unit/[....]
    new file:   test/unit/[....]
    deleted:    test/unit/[....]
    modified:   test/unit/[....]

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   test/unit/[....]

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    app/src/[....]/
    app/src/[....]/
    app/src/[....]/

(ファイル名を空白にしました)

自分が持っている変更だけをどのように隠しますかgit added(つまり、ステージングされていない変更や追跡されていないファイルではなく、「コミットされる変更」)なので、代わりに別のブランチに転送できますか?

16
peter-b

Gitの基本的なストレージメカニズムは「コミット」です。実際、git stashが行うのは、やや変わったコミットをいくつか行うことだけです。したがって、 Nick Volynkinの答え は正しいものです。ただし、多少の拡張を使用する可能性があり、より簡単な(まあ、潜在的に簡単な)方法があります。

私はgit stashの大ファンではありませんが、これを使用することに慣れている場合は、他の最も簡単な方法を次に示します。

  1. git stash save(別名git stash)。これにより、2つのコミットが書き込まれます。1つは現在のインデックスに基づいており、もう1つはまだステージングされていないワークツリーファイルを保持するためのものです。 (untrackedファイルを保持する必要がある場合は、-uフラグを追加してから、stashスクリプトでさらに3番目のコミットを追加できます。通常はただし、これらの追跡されていないファイルを作業ツリー内で追跡せずにそのままにしておくことができます。)これらのコミットはどのブランチにも存在せず、特別な「スタッシュ」参照にのみ存在します。その間、あなたはまだ「間違った」ブランチにいます。これを以下でwrongbrと呼びます。

  2. git checkoutこれらを配置するブランチ。今、あなたは正しい枝にいます。

  3. git stash apply --index。これは、ステップ1で作成された特別なスタッシュコミットを使用しますが、スタッシュにはそのままにしておきます(apply)。 --indexは非常に重要です。これは、stashスクリプトにインデックスファイルとステージングされていないファイルを分離しておくように指示します。つまり、ステージングされたファイルと以前に行ったステージングされていないセットアップ。

    すべてがうまくいけば、あなたは今、あなたが望むブランチへの変更をgit commitする立場にあります。以前にステージングされたファイルは再びステージングされ、ステージングされていないファイルはまだステージングされていません。これは、スタッシュを--indexapply-したためです。コミットはステージングされたファイルをコミットし、ステージングされていないファイルはステージングされないままにします。

  4. これで、他の「間違った」ブランチ(最初に隠し場所を作成した場所)とgit stash applyまたはgit stash pop--indexの有無にかかわらず戻ることができます。ステージングされていないファイルをクリーンアップする必要がある場合があります(そうしても安全です。ファイルはまだ隠されています):git reset --hard、次にgit checkout wrongbr、次にgit stash poppopapplyの後にdropが続くことに注意してください:wanttodropステップ3のスタッシュ(スタッシュには元の変更されたがステージングされていないファイルの唯一のコピーがあります)、これがapplyそこにありますが、(おそらく)doは隠し場所を削除したいので、popを使用しても問題ありません。

ただし、ステップ3には大きな潜在的な落とし穴があります。つまり、スタッシュが正しく適用されない可能性があります。もしそうなら、あなたは他の方法を使わなければなりません。これが、私がstashシステムを本当に好きではない理由の1つです。ハードケースでは失敗し、stashを使用しない場合に使用できるツールを知る必要があります。その場合、ほとんどの場合、これらのツールを使用できます...そして、それが確実に機能する場合の便利なショートカットとしてstashを使用します。


背景:コミットは現在インデックスにあるものをすべて取得します— git ls-files --cachedは完全なコンテンツを表示し、git statusはこれを「興味深い」コンテンツに切り詰めて、さらに有用な情報を追加します—そしてコミットをそれら、必要なすべてのツリーオブジェクトなどが含まれます。新しいコミットの親コミットは、現在のコミットが以前のものでした。

別のブランチで新しいコミットを行う必要があります。これを行う1つの方法は、現在のブランチで今すぐ作成することです。次に、そのコミットを別のブランチの新しい別のコミットにコピーします。 「別のブランチで新しい別のコミットにコミットをコピーする」には、git cherry-pickを使用できます。 git rebaseを使用できるのは事実です。内部では、git cherry-pick自体を使用しています。しかし、rebaseは完全に適切なツールではありません。これは、大量のチェリーピッキング用に設計されており、コミットは1つだけです。最後に、git resetを使用してブランチラベルを移動しますが、希望どおりではありません。あなたはそれを機能させることができますが、いくつかのより適切なツールがあります。

ただし、元の問題に戻りましょう。現在のインデックスを取得し、それを使用して新しいコミットを作成しますが、別のブランチにあります。これは、他に何もせずに今すぐ他のブランチに切り替えてから、新しいコミットを行うことができれば最も簡単です。

あなたができる可能性は高いです。 git checkout otherbranch、次にgit commitだけです。ここでは3つのケースが考えられます。

  1. 他のブランチはまだ存在していません。すごい! git checkout -b newbranchを使用して、現在の場所から作成します。次にgit commit。 「現在の場所」以外の場所から開始するように新しいブランチをリベースしたい場合を除いて、これで完了です。その場合は、新しいブランチでgit rebaseを使用します。ステージングされていないファイルを処理した後、後でそのリベースを実行できることに注意してください。

  2. もう1つのブランチは存在し、幸運なことに、git checkout otherbranchは正常に機能します。それを実行してコミットすれば、完了です。その後、ステージングされていないファイルに必要なブランチをgit checkoutできます。

  3. 最も厄介なケース:他のブランチは存在しますが、git checkoutは、コミットしていないものを上書きすることを通知します。

ケース3は、コミットまたはスタッシュする必要があるケースです。

ここで何をするかは、あなたが最も快適なものによって異なります。たとえば、最も簡単な代替方法として、上記の4ステップのstashメソッドを試すことができます。

ただし、私自身は、「間違った」ブランチで今すぐコミットしてから、もう一度コミットして(または、git stashを使用して)、ステージングされていないファイルを邪魔にならないようにします。これにより、rightブランチにgit cherry-pickできるコミットが得られます。動作する可能性のあるシーケンスの例を次に示します。

  1. git commitコミットしますが、「間違った」ブランチにあります(以下の参照用に現在のブランチをwrongbrと呼びましょう)。
  2. git stash saveは、ステージングされていない変更を保存します(または、-uを使用すると、追跡されていないファイルも保存します)。
  3. git checkoutコミットを実行するブランチ(例:git checkout rightbr)。
  4. git cherry-pick wrongbr。これが成功すれば、良いです。そうでない場合は、必要に応じてファイルを編集して、マージの問題が発生した後にクリーンアップしてから、結果をgit commitします。
  5. git checkout wrongbr:ステップ4でコピーしたコミットを削除することでこれを修正します。
  6. git reset --hard HEAD^:これにより、コピーしたコミットが削除されます。
  7. git stash pop(または同じことを行うgit stash apply && git stash dropapplyバリアントは、単にdropスタッシュの前に結果を検査する機会を与えます)。

ここでステップ4に注意してください:git cherry-pickは名前付きコミット(単に間違ったブランチにあるcommit-we-wantを含むwrongbrの先端)を取りますそれをその親と比較し、結果の差分を現在のブランチに適用しようとします。現在のブランチのファイルがwrongbrの対応するファイルと大きく異なる場合、これは3方向マージを行う必要があるかもしれません。これは、rightbrをチェックアウトして最初にコミットするという単純なケースで、複雑さが発生するのと同じ場所です。つまり、コミットする前にgit checkout rightbrだけを実行しようとしたときに「最も厄介な」ケースが発生したため、この長いバージョンを実行しているため、修正が必要になる可能性があります。これにより、元の4ステップのstashメソッドで問題が発生する可能性もあります。

18
torek
  1. すべてを隠しますが、インデックスは保持します(この隠し場所は(git addから)ステージングされ、ステージングされていない編集になります):

    git stash --keep-index

  2. インデックスを隠します。これは、手順1で隠した後に残っているすべてです(これは、隠したいものです)。

    git stash

  3. 手順1のスタッシュをすべてポップまたは適用(より安全)します(最新のものは常にstash@{1}であるため、現在はstash@{0}にあります)。

    git stash apply stash@{1}

  4. HEADからチェックアウトして、最初にインデックスに追加されたファイル(stash@{0}内のファイル)を復元します。

    git checkout HEAD ./path/to/files/to/reset ./another/path/to/other/file/to/reset

  5. 手順4で混乱した場合は、git reset HEAD --hardを試してすべてのローカル変更を消去し、手順3からやり直してください。

3
kilogic

それらのファイルをコミットしてから、コミットをリベースします。

3
Nick Volynkin