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?
Incidentally, the rename-checkout-...-rename
routine more closely represents what I expect from a command called stash
. In other words: save the state of my working directory now, and replace it later. There's no "merge" in this picture.
git stash pop pops the top stash off of the stack and merges it with your working environment. Merging a stash can definitely result in conflicts, if there are committed changes that touch the same piece of work. Resolve these conflicts in the same way as you would when merging two branches.
Otherwise, select the files to be taken, stage them with git add and finally commit them with git commit . Restore the unwanted files then with git checkout -- filename . @marckassy: But you could then git reset HEAD and git add -p to select what you want. To shut off the initial merge completely, add -s ours .
Manually (or ideally using some merge tool, see below) resolve the conflict(s). Use git restore --staged . to mark conflict(s) as resolved and unstage all files in the staging area. If you want to unstage only specific files, use the command git restore --staged <file> instead. You don't have to execute git add before.
Retrieving stashed changes You can reapply stashed changes with the commands git stash apply and git stash pop . Both commands reapply the changes stashed in the latest stash (that is, stash@{0} ). A stash reapplies the changes while pop removes the changes from the stash and reapplies them to the working copy.
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
). Where <branchname>
is the name of a new branch created by git
for the purpose of applying the stashed changes.
This pops the stash in a way that is guaranteed to be free of conflicts.
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 e.g.
git read-tree stash^{tree}
git checkout-index -af
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With