Search code examples
gitversion-control

How to stash properly on a rebased/reset upstream?


I am working on a repo from the original base A, to current HEAD (stashed B). In the meanwhile, the remote upstream was updated from A to C. I would like to rebase my local to C and stash B on top of that:

Remote: A -> C ---
             ---^
             |
Local:  A -> B

What I did was:

git stash push                # Save my current HEAD B in stash
git fetch remote
git reset --hard remote/main  # This set my current HEAD to remote C
git stash pop                 # Merge B into C

However after stash popped, new changes from remote C is missing and deleted during the stash merge. How do I do this properly? Should I do a rebase instead of reset, regular pull, merge, pull rebase, cherry-pick the stash commit, etc.?


Solution

  • After git fetch, you should use git rebase remote/main to replay your commits on top of the remote branch.

    git stash push / git stash pop has only reapplied the modifications you had on top of B, not B itself.
    git reset --hard ... has moved your branch to C without keeping any of the history specific to B.


    From your current situation :

    1. spot the <sha> of your commit B in your reflog, and create a branch on that :
    git reflog main
    
    # spot the sha for 'B', right before your 'reset to remote/main' action
    
    git branch my-main B
    
    1. stash your changes again, reapply B, then reapply your stash :
    git stash
    git cherry-pick B
    git stash apply
    
    1. if all has gone well (inspect the content of your repo), you can drop your latest stash and delete your branch my-main
    git stash drop
    git branch -D my-main