web-dev-qa-db-ja.com

マージの競合中の `git stash`

私たちは何か悪いことをしました。

実行しましたgit stash saveマージの競合中に、作業を復元できなくなりました。

私たちが試したこと:

git pull -Xours Origin master
git stash apply --index

そして:

 git pull Origin master
 git stash save --keep-index "merge conflicts"
 git stash apply stash@{1}

助けてください!

26
steven_moy

問題は、git stashがマージしようとしたブランチへの参照を保存しないことであるようです。マージ中、これはMERGE_HEADという名前の参照に保存されます。

それを修正して以前の状態に戻すには、マージしようとしたリビジョン(d7a9884a380f81b2fbf002442ee9c9eaf34ff68dのふりをしましょう)を見つけて、スタッシュを適用した後にMERGE_HEADを設定する必要があります。

次に、スタッシュを適用し(--indexを使用して、以前にステージングされたすべてのものを再ステージングします)、MERGE_HEADを設定します。

git stash apply --index
git update-ref MERGE_HEAD d7a9884a380f81b2fbf002442ee9c9eaf34ff68d
25
Evan Krall

今日も同じことをし、(試行錯誤の末に)別のアプローチを取り、隠蔽する直前の状態に戻して、競合の解決を続け、マージを完了できるようにしました。

まず、宛先ブランチで部分マージをアンスタッシュした後、競合が残っているファイルのリストをキャプチャしました(テキストファイルまたはエディタータブ)。競合がすでに解決されているファイルは、スタッシングの前にステージングされているため、これは、スタッシュ解除後のステージングされていないファイルのリストにすぎません。

$ git status
# 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:   myproject/src/main/Java/com/acme/package3/Class3.Java
#   modified:   myproject/src/main/Java/com/acme/package3/Class4.Java
#

次に、パッチを作成し、ブランチをマージ前の状態にリセットしました。

$ git diff HEAD > ~/merge-with-resolved-conflicts.patch
$ git reset --hard HEAD

次に、一時的なブランチ(マージ先のブランチから派生)を作成し、パッチを適用しました。

$ git checkout -b my-temp-branch
$ git apply ~/merge-with-resolved-conflicts.patch
$ git commit -a -m "Merge with resolved conflicts"

したがって、my-temp-branchのHEADには、競合が解決されたファイルや残りの競合があるファイルなど、マージされたすべてのものが含まれるようになりました。

次に、元のブランチに切り替えて再度マージし、gitステータスを確認しました

$ git checkout my-branch
$ git merge other-branch
$ git status

ステータスには、競合するファイルの完全なリストが表示されます。

# Unmerged paths:
#   (use "git add <file>..." to mark resolution)
#
#   both modified:      myproject/src/main/Java/com/acme/package1/Class1.Java
#   both modified:      myproject/src/main/Java/com/acme/package2/Class2.Java
#   both modified:      myproject/src/main/Java/com/acme/package3/Class3.Java
#   both modified:      myproject/src/main/Java/com/acme/package3/Class4.Java
#

次に、これら2つのファイルリストを比較する必要がありました。 2番目のリストにあるが、最初のリストにないファイルはすべて解決済みです(この例では、Class1.JavaとClass2.Java)。したがって、これらのファイルごとに、一時ブランチから競合が解決されたバージョンをプルしました(cherry-pickのように、コミット全体ではなく個々のファイルに対して)。

$ git checkout my-temp-branch myproject/src/main/Java/com/acme/package1/Class1.Java
$ git checkout my-temp-branch myproject/src/main/Java/com/acme/package2/Class2.Java

これを行った後、私は隠し場所の前の状態に戻ったので、残りの競合の解決を再開してマージをコミットすることができました。

1
mmindenhall

競合状態(インデックスと作業ディレクトリ)にある場合、git stashを実行することはできません。マージされていないエントリの設定でエラーが発生します。

あなたが本当に隠しをしたことを確認してください。 git stautsおよびgit stash showの出力を参照してください

0
manojlds

あなたの最後のコメントを与えられて:あなたは使うことができます

git stash megre --no-commit <branch>

変更をコミットせずにインデックスを「マージ」状態にする

次に、必要なもので変更します。

すでに隠し場所でマージを実行している場合:

git reset #to remove the "conflicts" flags
git checkout <initial commit> -- ./ #to revert everything to the previous working state,
git stash apply   #apply your changes

そして、すべてが望ましい状態になったら、git commit


bukzor のコメントについて:実際には、git checkout <tree-ish>git checkout <tree-ish> -- <files>には大きな違いがあります。

参照 から git checkout

  • git checkout <branch>:このフォームは、インデックス、作業ツリー、およびHEADを更新して、指定されたブランチまたはコミットを反映することにより、ブランチを切り替えます。

  • git checkout [-p|--patch] <tree-ish> -- <pathspec>:<paths>または--patchが指定されている場合、gitcheckoutはブランチを切り替えません。作業ツリー内の名前付きパスを、インデックスファイルまたは名前付き<tree-ish>(ほとんどの場合コミット)から更新します。

git checkout <initial commit>は確かにマージ情報を破棄します。

一方、git checkout <initial commit> -- ./(余分な-- ./に注意)は、マージ情報を保持し、追跡されたすべてのファイルを<initial commit>の状態に戻します。

0
LeGEC

これ(マージの競合中のgit stash pop)から抜け出すための私の解決策は次のとおりです。

  • 新しい(ローカル)ブランチを作成してチェックアウトするmytemporarybranch

    git branch mytemporarybranch && git checkout mytemporarybranch

  • これにコミットするmytemporarybranch

    git commit -m "私の厄介なマージとスカッシュ"

  • チェックアウトmyoriginalbranch

    git checkout myoriginalbranch

  • 正しくマージします(今回はスカッシュポップ/適用はありません!)

  • squashmytemporarybranchmyoriginalにマージしますブランチ

    git merge --squash mytemporarybranch

0
mmathieum