7

開発中、私は定期的にファイルの作業バージョンを git リポジトリに追加します (コミットはしません)。それらのファイルをコミットできる段階に到達するまで、これらのファイルの作業を続けます。したがって、レポは次のようになります

$ git status

# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   modified:   testfile1
#
# 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:   testfile1
#   modified:   testfile2

を実行してgit stashから を実行するとgit stash pop

# On branch master
# 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:   testfile1
#   modified:   testfile2

質問

  1. 以前のように git stash しないのはなぜですか?
  2. スタッシュ ポップを実行すると、新しい状態ではなく古い状態が取得されるように、変更を一度にスタッシュするにはどうすればよいですか?

現在、私は手動で行っています

git stash --keep-index
git stash
git stash pop
git add <stashed_files>
git stash pop

これに関する問題は

  1. 隠してポップするには5つのステップが必要で、私は2を探しています
  2. 2 つの背中合わせの隠し場所があったことを覚えていないことがあり、これが作業を少し複雑にしています。

編集-テストサーバーで同様の方法で作業しているため、コマンドラインソリューションを好みます。

4

2 に答える 2

5

これはすでに回答されているようですが、もう少し追加させてください。警告: にバグレットがありgit stashます。

git stashを使用せずにor git stash save(デフォルトではsaveこれらは同じものです) を実行する-pと、stashスクリプトはgit-coreディレクトリに存在し、その場所は git のインストールによって異なり/usr/libexec/git-coreます/usr/local/libexec/git-core。または場合によっては 3) 親コミット。順番に、これらのコミットは次のとおりです。

  • 現在のインデックス
  • -uまたは、追跡されて-aいないファイル、さらには無視されたファイル(およびgit clean作業ディレクトリからそれらを捨てるためにも使用されます)
  • 現在の作業ディレクトリとHEADコミットの間の差分に基づく作業ディレクトリ (これがバグレットのソースです。以下を参照してください)。

refs/stash次に、これらのコミットの最後の作業ディレクトリ コミットを指すように設定します。このコミットの親は次のとおりです。

  • stash^(最初の親)としての HEAD コミット
  • stash^2(2 番目の親)としてのインデックス コミット
  • 未追跡/無視されたコミットstash^3(存在する場合) (3 番目の親)。

このスタッシュには、実際には、スタッシュ時に配置されていたすべてが含まれていますが、「スタッシュ前の状態」を使用git stash pop --indexまたは復元する場合に、バグレットが最もよく表示されます。git stash apply --index(git stash apply以下でpopは のみを使用しますが、applyその後に . が続きdropます。)

さて、あなたが指摘したように、実行する前にいくつかのことを慎重にステージングしたとしても、git stash apply実行すると多くのファイルが得られます。これは、別のブランチなどをチェックアウトした場合や、実行前にいくつかのファイルをステージングした場合など、作業ディレクトリの状態に関係なく、このようにこれらの変更をマージする方がはるかに簡単だからです。(実際には、git のマージ コードを使用して作業ディレクトリの変更を取り込みます。)changes not staged for commitgit stash savegit stash applygit stash apply

git stash apply --indexただし、を実行するstash、スクリプトは最初に、元の. (まだ何もステージングされていない場合は、元の状態に戻ります。) それができると仮定して、同様に (再びマージ メカニズムを使用して) 作業ディレクトリを設定しようとします。インデックスを適切に設定できない場合は、インデックスに対して何もせず、 なしで再試行することを提案します。save--index

ここで、バグレットの出番です。たとえば、basefile何も変更していない というファイルから始めるとします。変更を加えて、これをステージングします。

$ cat basefile
base
$ git status --short
$ echo add to basefile >> basefile; git add basefile

しかし、作業ディレクトリのコピーにHEADリビジョンからの変更を加えないようにすることにしました。

$ ed basefile
21
2d
w
5
q
$ git status --short
MM basefile

ここで注意が必要な点は、インデックスで変更され、次に work-dir で再度変更されることですが、2 回目の変更でコミットbasefileの内容に戻ります。HEADを実行するgit stash saveと、stash スクリプトは誤ってインデックスバージョンを進行中のバージョンであるかのように記録します。

ここで agit stash apply --indexを実行すると、次のようになりますgit status --short

$ git stash save
Saved working directory and index state WIP on master: 94824e1 initial
HEAD is now at 94824e1 initial
stash created
$ git stash apply --index
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   modified:   basefile
#
$ git status --short
M  basefile

ここで、git はインデックスのバージョンをインデックスに復元し、作業ディレクトリのバージョンをインデックスのバージョンと同じものに設定しています。

$ cat basefile
base
add to basefile

stash スクリプトの修正は一言だけの変更ですが、今のところ誰も気に入っていないようです。おそらく問題は、stashを なし --indexで適用すると、インデックスの変更 (余分な行add to basefile) が何もないものと効果的に結合されるため、work-directory バージョンに余分な行が含まれることです。ただし、インデックスと作業ディレクトリの両方のバージョンが異なる場合の動作とは一致しません。

$ git stash drop
Dropped refs/stash@{0} (61c83c866bc522c58df62320b77e647ffd28aa95)
$ echo base > basefile
$ git status --short
$ echo add to basefile >> basefile
$ git add basefile
$ ed basefile
21
2c
different change
w
22
q
$ git status --short
MM basefile
$ git stash save
Saved working directory and index state WIP on master: 94824e1 initial
HEAD is now at 94824e1 initial
$ git stash apply
# On branch master
# 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:   basefile
#
no changes added to commit (use "git add" and/or "git commit -a")
$ cat basefile
base
different change

ここでは、インデックスとワーク ツリーの変更を「一緒につぶす」ことによって変更しますが、適用せずに適用すると、ワーク ツリーの変更のみ--indexが回復されます。

(幸いなことに、apply代わりにpopを使用しているので、ここで考えを変えることができます:

$ git reset --hard HEAD
HEAD is now at 94824e1 initial
$ git stash apply -q --index
$ git status --short
MM basefile

index と work-dir のバージョンを見ると、 の両方のバージョンが表示されますbasefile。)

(stash スクリプトの修正は、次の行を次のように変更HEADすることです。$i_tree

git diff --name-only -z HEAD -- >"$TMP-stagenames" &&

118 行目あたり。これを git メーリング リストに投稿したところ、... コオロギが出てきました。:-) )

于 2013-10-10T21:16:31.813 に答える