web-dev-qa-db-ja.com

コミットせずにgit stashの競合を解決するにはどうすればいいですか?

この質問で尋ねられたように 、私はコミットにすべての修正を加えずに矛盾するgit stash popを解決する方法を知りたい(ちょうど衝突のない "git stash pop"のように)。

私の現在のアプローチは私がこのようにしているので非常にクールです。

git stash pop -> CONFLICT
git stash drop
[resolve conflict]
[add conflict files]
git reset HEAD <all files that are in commit-mode>

[更新]それを再現する方法:

mkdir foo; cd foo; git init
echo "1" > one
echo "2" > two
git add -A; git commit -m "first"
echo "1.1" > one
echo "2.1" > two
git stash
echo "2.2" > two
git commit -a -m "second"
echo "Only this file would stay in HEAD without the conflict" > third
git add third
git stash pop
git status

2016-06-27:scyからの解決策のような回避策が空のHEADに対してのみ有効であるがHEAD doesnという初期の問題を修正しないことを示すために、例に 'third'と呼ばれる新しいファイルを追加した。 git stash popの場合と同じ内容で、競合することはありません。

403
Sven

他の答えに従ってはいけません

まあ、あなたはそれらに従うことができます:)。しかし、コミットを実行してからブランチをリセットしてそのコミットを削除すること、および他の回答で提案されている同様の回避策がこの問題を解決するためのきれいな方法ではないと思います。

きれいな解決策

次の解決策は私にはずっときれいに思えるし、またそれは Git自身が示唆している - 衝突しながらリポジトリでgit statusを実行しようとする:

Unmerged paths:
  (use "git reset HEAD <file>..." to unstage)
  (use "git add <file>..." to mark resolution)

それではGitが提案したことをしましょう(無駄なコミットをすることなく)。

  1. 手動で(またはマージツールを使用して(下記参照))、競合を解決してください。
  2. git resetを使用して競合を解決済みとしてマークし、変更をステージング解除します。パラメータなしで実行することができ、Gitはインデックスからすべてを削除します。以前にgit addを実行する必要はありません。
  3. 最後に、git stash dropで隠し文字を削除します。Gitはそれを矛盾して行わないからです。

コマンドラインに翻訳:

$ git stash pop

# ...resolve conflict(s)

$ git reset

$ git stash drop

デフォルトの動作の説明

競合を解決済みとしてマークする方法は2つあります。git addgit resetです。 git resetは競合を解決済みとしてマークし、ファイルをインデックスから削除しますが、git addも競合を解決済みとしてマークしますが、ファイルをインデックスに残します。

競合が解決された後にインデックスにファイルを追加することは意図的です。このようにして、前のスタッシュからの変更と競合が解決された後に行った変更を区別することができます。気に入らなければ、git resetを使ってインデックスからすべてを削除することができます。

マージツール

3-way mergeツール のいずれかを使用して競合を解決することを強くお勧めします。 KDiff3Meld など、手動ではなくそれは通常、それ自身で自動的にすべてまたは大多数の衝突を解決します。それは 巨大な 時間の節約です!

Originから取得するために変更を隠蔽するこのシナリオがあるとします。おそらく、あなたのローカルな変更は、設定ファイルの中のdebug: trueに過ぎないからです。今、あなたは引っ張って、誰かがそこに新しい設定を導入し、衝突を引き起こしています。

git statusは言う:

# On branch master
# Unmerged paths:
#   (use "git reset HEAD <file>..." to unstage)
#   (use "git add/rm <file>..." as appropriate to mark resolution)
#
#   both modified:      src/js/globals.tpl.js
no changes added to commit (use "git add" and/or "git commit -a")

はい。私はGitが提案したことに従うことにしました:私は衝突を解決し、そして誓約しました:

vim src/js/globals.tpl.js
# type type type …
git commit -a -m WIP   # (short for "work in progress")

これで私の作業コピーは必要な状態になりましたが、必要のないコミットを作成しました。作業コピーを変更せずにどうやってそのコミットを取り除くのですか?ちょっと待って、そのための一般的なコマンドがあります!

git reset HEAD^

私の作業コピーは変更されていませんが、WIPのコミットはなくなりました。それこそまさに私が欲しかったものです! (ここでは--softを使用していません。あなたのスタッシュに自動マージされたファイルがある場合、それらは自動ステージングされます。したがって、これらのファイルはresetの後に再びステージングされます。

git stash popのmanページは "状態を適用すると衝突で失敗する可能性があります。この場合はstashリストから削除されません。衝突を手動で解決してgit stash dropを呼び出す必要があります。その後手動で」 これがまさに私たちが今していることです。

git stash drop

そしてやった。

290
scy

競合を解決するために行った変更を追加する代わりに、変更をステージングせずに競合を解決するためにgit reset HEAD fileを使用できます。

ただし、このコマンドを2回実行する必要があります。 1回は競合を解決済みとしてマークし、もう1回は競合解決ルーチンによって実行された変更をステージング解除します。

現時点ではありませんが、これら両方を同時に行うリセットモードがあるはずです。

82
ComputerDruid
git checkout stash -- .

私のために働いた。

注意 :これはstashからの変更を作業コピーにマージしようとしないので危険であるかもしれませんが、代わりに を上書きして を上書きします。だからあなたはあなたの未確定の変更を失うことができます。

18
mr.musicman

これはあなたが探している答えかもしれませんが、私はまだこれを個人的に試したことはありませんが、それはそれがトリックをするかもしれないようです。このコマンドを使うと、GITはコミットのためにそれらをすべて追加しようとせずに、以前のように変更を適用しようとします。

git stash apply --index

これが詳しい説明です。

http://git-scm.com/book/en/Git-Tools-Stashing

4
Marco Ponti
git add .
git reset

git add .は、あなたが衝突を解決したことをgitに伝えるすべてのファイルをステージングします。

git resetはコミットを作成せずにすべてのステージファイルをアンステージします

4
Aaron Goldman

git stash branchは機能し、あなたに代わって新しいブランチを作成し、あなたがあなたの仕事を隠したときに行っていたコミットをチェックアウトし、そこであなたの仕事を再適用します。 check これ

2
cherish

私が見つけた最速の方法は、衝突を解決してからgit add -uを実行し、次にgit reset HEADを実行することです。これにはコミットも含まれません。

2
Jammer

git stashの質問 によると、衝突を修正した後、git add <file>が正しい行動方針です。

このコメント を読んだ後、私は変更が自動的にインデックスに追加されることを理解しました(設計上)。 git add <file>が競合解決プロセスを完了したのはそのためです。

1
samgrigg