how to pop git stash without triggering an auto
The short version of this question is this: how can I pop the git
stash without triggering an auto-merge?
Now for the longer version...
Consider the following toy example of an alternative to git stash ... + git pull ... + git pop
.
First, git status
shows that the only modification in the working directory is to some tracked file foo
.
# 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: foo
#
no changes added to commit (use "git add" and/or "git commit -a")
Now, in order to reset the working directory to a clean state, as a pre-requisite for running git pull
, I temporarily rename the modified file foo
(to some untracked name), and restore the version of foo
in HEAD
...
% mv foo foo.$(date +%Y%m%dT%H%M%S)
% git checkout foo
% git status
# On branch master
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# foo.20130508T110014
nothing added to commit but untracked files present (use "git add" to track)
OK, now I run git pull
, which, for the sake of this example, we may assume is a fast-forward:
% git pull
Lastly, I restore the temporarily renamed foo
.
% mv foo.20130508T110014 foo
...and I'm back to
% git status
# 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: foo
#
This is the "moral equivalent" of a git stash save + git pull + git stash pop
, EXCEPT that the former, and not the latter, is immune to "merge conflicts", like this one:
% git stash save 'WIP'
% git pull
% git stash pop
Auto-merging foo
CONFLICT (content): Merge conflict in foo
How can I replicate the rename-checkout-pull-rename
sequence above using git stash save + ... + git stash pop
, without triggering an auto-merge?
EDIT: Incidentally, the rename-checkout-...-rename
routine more closely represents what I expect from a command called stash
. IOW: save the state of my working directory now, and replace it later. There's no "merge" in this picture.
I belatedly realized that git
already provides an extremely simple solution to the problem that motivated this question (namely an automatic merge with the potential to put the repository in a "unmerged state").
All one needs to do is to use
git stash branch <branchname> [<stash>]
instead of git stash pop
(or git stash apply
).
This pops the stash in a way that is guaranteed to be free of conflicts. Easy-peasy-lemon-squeezy.
stash
merges, that's just how it works.
You can achieve the non-merge-y stash with with write-tree
read-tree
and checkout-index
. Here's a worked example for doing this to achieve a pristine test environment.
To just brute-force a no-merge stash apply, you could eg
git read-tree stash^{tree}
git checkout-index -af
The fact that you are seeing a merge conflict means that there was a change in the foo
file that you pulled from the server. So, copying your file over and moving back will completely nuke all changes from the repo in the foo
file. If you commit that, the other person that committed changes to foo
will hate you.
The answer to your question depends on what you are trying to accomplish. Are you trying to see what the changes on the server were compared to your code? Are you trying to avoid dealing with other people's code until you are done?
If you just want to see what the change to the branch were, you can use git fetch
instead of git pull
and compare your current code with that. Or, if you don't want to merge your changes now, consider working in a separate branch, or not pulling until you are ready to merge.