Last active
August 29, 2015 14:04
-
-
Save here/4f3af6dafdb4ca15e804 to your computer and use it in GitHub Desktop.
How to resolve git stash pop merge conflict with unstaged changes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# trying to replicate and solve this situation: | |
# http://stackoverflow.com/questions/8515729/aborting-a-stash-pop-in-git/ | |
# tl;dr, if you didn't have any staged changes, this should work: | |
git diff --name-only --cached|xargs git checkout --ours HEAD | |
git ls-tree stash@{0}^3 --name-only|xargs rm | |
# If there were no untracked files introduced from the stash | |
# then the second command will fail with | |
# fatal: Not a valid object name stash@{0}^3 | |
# this is expected. | |
# Questions: | |
# Q: Is it possible to have merge conflicts in a file with unstaged changes? | |
# A: I don't think so since the git stash pop will fail as shown below. | |
# Q: Does this fail in some cases with staged changes? | |
# A: tbd... (See end, and stackoverflow answers) | |
# Without staged changes | |
# Setup and resolution | |
# Use `setopt interactivecomments` to ask shell to ignore # comments | |
git init | |
touch a | |
touch m | |
git add . | |
git commit -m "a m" | |
echo one > a | |
touch b | |
git add b | |
git commit -am "a=one b" | |
echo stash > m | |
echo stash > b | |
echo stash > c | |
git stash save -u "m=stash b=stash c=stash" | |
echo one > b | |
# git stash pop | |
# fails with "Your local changes to the following files would be overwritten by merge" | |
# fails with "Please, commit your changes or stash them before you can merge." | |
git commit -am "b=one" | |
# touch c | |
# git stash pop | |
# fails with "c already exists, no checkout" | |
echo two > a | |
touch d | |
git stash pop | |
# Result: | |
# Merge succeeded in m (theirs) | |
# Conflict in b | |
# Unstaged in a | |
# Untracked in c and d | |
# Goal: | |
# Reverse changes to successful merge m | |
# Keep our version in merge conflict b | |
# Keep our unstaged a | |
# Keep our untracked d | |
# Delete stashed untracked c | |
# Step 1 | |
# List all staged or conflicting files by name | |
# Checkout each of these files using --ours HEAD which will: | |
# - undo successful merges to HEAD with old version | |
# - resolve any conflicted files with old version | |
# - leave any unstaged or untracked files untouched | |
git diff --name-only --cached | xargs git checkout --ours HEAD | |
# Unstaged and modified | |
# No action needed, they are all ours or the stash pop would fail | |
# Untracked files | |
# Goal: delete untracked files which were introduced by the stash pop | |
# see also: http://stackoverflow.com/questions/12681529/in-git-is-there-a-way-to-show-untracked-stashed-files-without-applying-the-stas | |
# | |
# List all untracked files from the stash | |
# Delete each of these files using xargs rm | |
git ls-tree stash@{0}^3 --name-only | xargs rm | |
######### | |
# Staged changes: | |
# If you have staged files, it is possible to end up in a situation where it is more difficult to tell if a | |
# change originated from the stash. A modified and staged file may contain changes existing in both the | |
# stash and the pre-stash state. | |
# | |
# In the following case, a=two both before and after the stash. | |
# | |
# I believe the above commands will still work in most of these cases, but I am suspect of clever evasion. | |
git init | |
echo one > a > b | |
git add a b | |
git commit -a -m "a=one b=one" | |
echo two > a | |
echo three > b | |
git stash | |
echo two > a > b | |
git add a b | |
git stash pop |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment