git stash->隠された変更を現在の変更とマージする


187

私は自分のブランチにいくつかの変更を加えましたが、そのブランチに必要な他の変更をすべて隠していたのを忘れていました。私が欲しいのは、隠しておいた変更を現在の変更とマージする方法です。

これを行う方法はありますか?

便宜上、結局私は最終的にあきらめて最初に現在の変更をコミットし、次に私の隠された変更をコミットしましたが、私は一挙にそれらを取り入れることを望んでいました。



ジョシュアの答えは受け入れられた答えでなければなりません。このstackoverflowの投稿は、この質問の最初のGoogleリンクです。インターネットに正しい答えを与えてください!
ジェローム2018

回答:


272

コミットされていない変更がインデックスに追加された場合(つまり、を使用して「ステージング」された場合git add ...)、git stash apply(そしておそらく、git stash pop)実際に適切なマージが行われることを発見しました。衝突がない場合、あなたは黄金です。そうでない場合は、通常どおりで解決するgit mergetoolか、エディタで手動で解決します。

明確にするために、これは私が話しているプロセスです:

mkdir test-repo && cd test-repo && git init
echo test > test.txt
git add test.txt && git commit -m "Initial version"

# here's the interesting part:

# make a local change and stash it:
echo test2 > test.txt
git stash

# make a different local change:
echo test3 > test.txt

# try to apply the previous changes:
git stash apply
# git complains "Cannot apply to a dirty working tree, please stage your changes"

# add "test3" changes to the index, then re-try the stash:
git add test.txt
git stash apply
# git says: "Auto-merging test.txt"
# git says: "CONFLICT (content): Merge conflict in test.txt"

...これはおそらくあなたが探しているものです。


tl; dr

git add最初に実行します。


8
そのようなハックですが、ちょっと、それは機能し、これを行う唯一の方法のようです。git stash apply --force何かあったらいいのになあ。
Matt Kantor 2013

13
実際、これはハックではありません-インデックスの変更に簡単に戻すことができるため、これは必要なものに対する改善です。
hoffmanc 2014

2
うわー、この動作は本当にgitが意図したものですか?
edi9999

9
gitが「意図した」ものはないと思います。私の直感は今や、gitが偶然そうすることです。
Profpatsch 2016年

5
これは完璧なソリューションです。私はちょうどでしたgit add .git stash applyそして、git resetコミットを加えることなく、私の作業の変更やマージにスタッシュを適用します。
スティーブンスミス

70

実行中git stash popまたはgit stash apply本質的にはマージです。stashで変更されたファイルが作業コピーでも変更されない限り、現在の変更をコミットする必要はありませんでした。その場合、次のエラーメッセージが表示されます。

error: Your local changes to the following files would be overwritten by merge:
       file.txt
Please, commit your changes or stash them before you can merge.
Aborting

その場合、1ステップで現在の変更にスタッシュを適用することはできません。git rebase本当に2つのコミットが必要ない場合は、変更をコミットし、stashを適用して再度コミットし、2つのコミットを押しつぶすことができますが、それだけの価値があるほど面倒かもしれません。


1
私はそのメッセージを受け取りました-変更は競合しませんが、stash / applyを使用して同じファイルを共有しますか?
Bemis

1
申し訳ありませんが、それは私が「マージ競合」によって意味したものですが、それは言葉の選択が不十分でした。エラーメッセージはかなり最終的なものだと思います。作業コピーで変更されたファイルがstashでも変更された場合、stashを適用できません。可能な回避策を使用して回答を更新しました。
ブランダン2012

3
私はこれをすべての場合の答えとは考えません。開発中に何かをテストしたかったので、特定のファイルの一連の変更の一部のみを隠していた可能性があります。また、WIPであるため、この時点でファイルの現在のコンテンツをコミットしたくない(またはまったくコミットしない)こともできます。隠された変更を現在のブランチにマージできないのはgitの実際の問題です
Thomas Watson

21
ジョシュアワーナーの答えは正しいとマークされたものでなければなりません。stashをマージし、変更をステージングし、stashを適用し、競合を処理してから、(必要に応じて)変更のステージングを解除します。
Vroo 2013年

4
「2つのコミットが本当に必要ない場合は、git rebaseを使用して、変更をコミットし、stashを適用して再度コミットし、これら2つのコミットを押しつぶすことができます。これの代わりに、次のことを実行できます。変更をコミットし、スタッシュを適用してから、を実行しgit commit --amendます。
gabe 2015年

27

私が欲しいのは、隠された変更を現在の変更とマージする方法です

これを行う別のオプションを次に示します。

git stash show -p|git apply
git stash drop

git stash show -p最後に保存されたスタッシュのパッチが表示されます。git applyそれを適用します。マージが完了したら、マージされたスタッシュをで削除できますgit stash drop


1
ありがとうございgit stash popます。マージが問題なく適用される場合に、なぜこれを実行しないのかわかりません...
Iguananaut

拡張バージョン:git stash show -p --no-color | git apply --3way--3way=パッチが失敗した場合、3者間マージにフォールバック)。
DmitrySandalov

しかし、stashエントリが最初に作成されたときに、stashされたコンテンツとコミットバックの間にgit stash show -p差分を作成しますます。したがって、これはOPが行った作業ファイルの変更を上書きします。
ポールF.ウッド

なぜ上書きするのですか?で生成されたdiff は、競合することなく実行できる場合、git stash show -pによってマージされgit applyます。
ks1322

1

私がこれを行う方法は、git add次にこれを最初にすることgit stash apply <stash code>です。これが最も簡単な方法です。


4
これは受け入れられた回答のtl; drの正確なコピーではないのですか?
RomainValeri

0

@Brandanによって提案されたように、これは私が回避するために必要なことです

error: Your local changes to the following files would be overwritten by merge:
       file.txt
Please, commit your changes or stash them before you can merge.
Aborting

このプロセスに従ってください:

git status  # local changes to `file`
git stash list  # further changes to `file` we want to merge
git commit -m "WIP" file
git stash pop
git commit -m "WIP2" file
git rebase -i HEAD^^  # I always use interactive rebase -- I'm sure you could do this in a single command with the simplicity of this process -- basically squash HEAD into HEAD^
# mark the second commit to squash into the first using your EDITOR
git reset HEAD^

そして、への完全にマージされたローカル変更が残り、fileさらに作業/クリーンアップを実行するか、単一の適切なコミットを行う準備が整います。または、マージされたコンテンツfileが正しいことがわかっている場合は、適切なメッセージを書き込んでスキップできますgit reset HEAD^


0

たぶん、ブランチから(difftoolを介して)マージするのは最悪の考えではありません...はい...ブランチ!

> current_branch=$(git status | head -n1 | cut -d' ' -f3)
> stash_branch="$current_branch-stash-$(date +%yy%mm%dd-%Hh%M)"
> git stash branch $stash_branch
> git checkout $current_branch
> git difftool $stash_branch

0

あなたは簡単にできます

  1. 現在の変更をコミットします
  2. 隠しておけば、衝突を解決できます
  3. stashからの変更をコミットする
  4. コミット元のソフトリセット(最後の正しいコミット)

-1

別のオプションは、ローカルのコミットされていない変更の別の「git stash」を実行してから、2つのgit stashを結合することです。残念ながら、gitには2つのスタッシュを簡単に組み合わせる方法がないようです。したがって、1つのオプションは、2つの.diffファイルを作成して両方に適用することです。少なくとも、追加のコミットではなく、10ステップのプロセスは必要ありません:|

方法:https : //stackoverflow.com/a/9658688/32453


これは、1つの差分を適用する問題を2つの差分を適用する問題に変えます。さらに、受け入れられたソリューションはコミットを含まず、単なるステージであり、単一のコマンド(git add)のみです。(私は賛成投票ではありません。)
Eike

少なくとも私にとっては、よりシンプルで、ブードゥーマジックが少なく感じられます...乾杯!
ロジャーパック、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.