6

It happens that information about a merge are lost after we do a stash. A usual merge and a stashed merge are compared below.

Right: merge + push

git merge release-2013-10-29
# Everything works, cool
git commit -am "Upgraded to release 2013-10-29"
git push origin dev

Result is as expected, a merge commit:

enter image description here

Wrong: merge + stash + push

Here I am in a scenario where I need to stash the merge changes just in order to have a look at the previous-to-the-merge behaviour.

git merge release-2013-11-06
# Conflicts fixed, but detected inappropriate behaviour
git stash
git stash pop
git commit -am "Upgraded to release 2013-11-06"
git push origin dev

Result: this commit is not a "merge" anymore. We also lost all single authored commits contained by the merge, just like if I would have made all these changes.

enter image description here


So, shouldn't we stash anything when merging? How to avoid such behaviour then?

Community
  • 1
  • 1
Stéphane Bruckert
  • 21,706
  • 14
  • 92
  • 130
  • Just don't use `stash`. There is nothing `stash push/pop` does that `git commit -a -m stash-commit` and `git checkout branch-with-stash-commit && git reset HEAD^` already does flawlessly (without any akward behaviour like you describe `stash` have). I really see no reason to use `git stash` any longer, I consider it to be a reliek from the very early git development. – hlovdal Jul 10 '14 at 14:09
  • 1
    I am not sure to follow your point. Once I fixed *a lot* of conflicts from the merge, I needed to revert back to the before-the-merge state "just to check something". None between `commit`, `checkout` or `reset` would temporarily save the conflicts I took a long time to fix. Only `stash` would. Or are you trying to say that I should just have committed my files without having verified the previous behaviour and even with some "wrong" code/merges? And more particularly, than no-one should stash anything, ever? – Stéphane Bruckert Jul 10 '14 at 14:25

1 Answers1

5

When you do a merge, git stores a reference to the branch you're merging in MERGE_HEAD. But it seems like git stash doesn't save the reference.

You can try to set the MERGE_HEAD back to the commit which you were merging after applying the stash:

Suppose you're merging release-2013-11-06 branch onto master, and the last commit there is - 3be2c99, then you can do:

git stash apply --index
git update-ref MERGE_HEAD 3be2c99
git status
# All conflicts fixed but you're still merging
# ....

Notice the usage of --index while applying the stash. That is required to get the changes back in the index, else you will get the stashed changes only in the working tree.

P.S: Ideally you should avoid stashing your uncommitted merge.

Community
  • 1
  • 1
Rohit Jain
  • 209,639
  • 45
  • 409
  • 525
  • I would underline the usage of `--index` with `git stash pop`: without it, the changes would not be applied to the index, only to the work tree, and a "conflicts resolved" state implies that the "ok to be committed" state of files which had conflicts are in the index. – kostix Jul 08 '14 at 17:55
  • @kostix Yup, added a note about it :) – Rohit Jain Jul 08 '14 at 17:58
  • @StéphaneBruckert There is a minor correction in my answer, please re-look. Actually MERGE_HEAD should point to the commit in the branch you're merging, i.e., *release-2013-11-06* in your case. – Rohit Jain Jul 08 '14 at 18:05
  • Argh. Note that if you try to apply the `MERGE_HEAD` after committing with a plan to amend the commit, you'll (well, _I_ was, anyhow) be told to take a hike. `fatal: You are in the middle of a merge -- cannot amend.` – ruffin Jun 06 '22 at 20:02