4

Suppose that upon running git stash pop, one gets a CONFLICT message (resulting from a failed auto-merging attempt).

Is there a quick way to tell git to resolve all conflicts in favor of the stash that was just popped?

EDIT: I just wrote the following script to test the two alternatives proposed. It

  1. creates a fresh git repo in the directory /tmp/$1, and cds to it;
  2. creates a first version of a file and commits it;
  3. makes some changes to the file and stashes the file;
  4. makes other changes to the file (including both conflicting and non-conflicting changes), and commits these changes; and finally
  5. pops the stash

This sets the stage for comparing the two proposed methods. Here's the script:

shopt -s expand_aliases
alias gcommit='git commit -q --allow-empty-message -m ""'
alias gmerge='git merge -q --no-edit'

TESTDIR=/tmp/$1
rm -rf "$TESTDIR"
mkdir -p "$TESTDIR"
cd "$TESTDIR"

git init -q
touch chiasmus.txt
git add . && gcommit

cat <<EOF > chiasmus.txt
ask

what

...
EOF
gcommit -a

cat <<EOF > chiasmus.txt
ask
not
what
your country can do for you
...
EOF
git stash -q

cat <<EOF > chiasmus.txt
quote:
ask

what
you can do for your country
...
jfk
EOF
gcommit -a

git stash pop -q

Then I ran

% bash gittest.sh checkout
% bash gittest.sh merge

% cd /tmp/checkout
% git checkout --theirs $(git diff --name-only --diff-filter=U)

% cd /tmp/merge
% git reset -q --hard
% git merge -q --no-edit --squash -Xtheirs stash
Auto-merging chiasmus.txt
Squash commit -- not updating HEAD
Automatic merge went well; stopped before committing as requested

% diff /tmp/{checkout,merge}/chiasmus.txt
0a1
> quote:
5a7
> jfk

Therefore, it looks like the "checkout" option does lose the non-conflicting changes. As it happens, though, this option more closely matches what I was really after, namely, have git pop behave more closely to what I expect it to do: return me to where I was when I ran git stash, period. No auto-merge, etc. (IOW, my question, as asked, really did not accurately reflect what I was after. It's as if meagar read my mind somehow.)

Community
  • 1
  • 1
kjo
  • 27,601
  • 42
  • 124
  • 225

2 Answers2

3

You need to run git checkout --theirs <file> for each file in conflict:

git checkout --theirs `git diff --name-only --diff-filter=U`
Community
  • 1
  • 1
meager
  • 209,754
  • 38
  • 307
  • 315
  • 1
    But if there's a file with a mix of conflicting and non-conflicting local changes, this will drop the non-conflicting changes won't it? – jthill May 09 '13 at 14:43
  • 1
    No. `--diff-filter=U` will show only unmerged changes, that is, files marked as containing conflicts. – meager May 09 '13 at 14:46
  • 1
    How does checking out the --theirs version preserve the non-conflicting change hunks in the --ours version? – jthill May 09 '13 at 14:49
2

Just do the merge yourself, instead of the stash pop. The stash commit's named stash.

git merge --squash -Xtheirs stash
jthill
  • 42,819
  • 4
  • 65
  • 113
  • Thanks. I decided to accept your answer because it more accurately matches what I actually asked for, even though, ironically, meagar's solution is closer to what I was *really* after... – kjo May 09 '13 at 20:30
  • Heh. Yeah, I noticed your unhappiness with my answer to the question you asked earlier. I confess I think the two-command sequence I gave there satisfies what you asked for there exactly. But if the low-level commands turn you off, you could also instead of meagar's answer skip the stash pop and `git checkout stash -- .` though that will leave any new files in your pulled commit still tracked. – jthill May 09 '13 at 20:52