26

If I do git checkout my-super-branch git tells me:

error: Your local changes to the following files would be overwritten by checkout:
    somedir/somefile.py
Please, commit your changes or stash them before you can switch branches.
Aborting

Is there a simple way to tell git to do stash+pop automatically?

guettli
  • 25,042
  • 81
  • 346
  • 663
  • 1
    Make an alias or a shell script that will do that for you. Note though that `stash pop` can be a *dangerous* operation, and you really shouldn’t make this an automatic step. Applying a stash can cause conflicts which you will need to resolve manually, and if you used `stash pop` then the original stash is gone, so you have no way to go back. – poke Jan 26 '18 at 08:59
  • 2
    Are you sure you want this to happen automatically? That could be quite annoying in some scenarios (e.g. you've modified a file that doesn't exist in `my-super-branch`). – Oliver Charlesworth Jan 26 '18 at 09:00
  • You can use git hooks for that. – Ayushya Jan 26 '18 at 09:00
  • 7
    @poke stash pop does not drop the stash entry if the stash does not apply cleanly. – mmlr Jan 26 '18 at 09:07
  • @poke you say "stash pop can be a dangerous operation". I don't understand this. Yes, a conflict can happen and some files can contain the well known strings of a conflict. Do you consider this "dangerous"? If not, what is dangerous about this operation? – guettli Jan 26 '18 at 09:23
  • 1
    @mmlr Oh, you’re right! For some reason, I always thought that it would remove the stash in any case. Good to know! ([This](https://codingkilledthecat.wordpress.com/2012/04/27/git-stash-pop-considered-harmful/) still applies though which is why I personally avoid `pop`) – poke Jan 26 '18 at 09:38
  • @guettli I consider getting a conflict mid-work quite dangerous, yes. Unless you explicitly stash and apply, there is no guarantee about the state the current work is in, and it’s difficult to track what actual changes are there when this happens automatically for you. But when you stash explicitly, you are conciously doing that, and you are probably somewhat aware of what changes you are introducing. So you have more control over everything and are more likely to be able to handle a possible conflict. – poke Jan 26 '18 at 09:42

6 Answers6

17
git checkout -m target-branch

or

git checkout --merge target-branch

https://git-scm.com/docs/git-checkout/en#Documentation/git-checkout.txt---merge

jari
  • 171
  • 1
  • 2
  • 1
    So simply... Need to be the accepted answer. – vernou Nov 24 '22 at 15:49
  • 1
    @vernou This doesn't work with staged files. `> git checkout -m main fatal: cannot continue with staged changes in the following files: src/util.test.ts` – TMB Apr 21 '23 at 14:19
7

There is no command-line option for autostash on checkout. I created a script checkout.sh like this:

#!/bin/bash
git stash && git fetch && git checkout $1 && git stash pop

So I can use it with my chosen branch: checkout.sh my-branch

franbenz
  • 696
  • 1
  • 10
  • 16
3

Git allows Pipelining operations:

git stash && git fetch && git checkout your-branch && git stash apply

Your changes are still in stash as I used git stash apply.

Resolve conflicts if any.

In case you wish to remove your changes from stash after above call below:

git stash drop

Otherwise you could just use git stash pop

Vinay Prajapati
  • 7,199
  • 9
  • 45
  • 86
1

To stash your changes and move them onto another branch, add this to your .gitconfig:

[alias]
    stashonto = "!f() { if [ -z \"$1\" ] ; then echo 'Error: stashonto requires destination branch.\nExample: git stashonto master\nExample: git stashonto -b new-branch 98e7f99e' ; else git stash --include-untracked && git checkout $* && git stash apply ; fi;  }; f"

That creates a git alias that calls a shell function so we can chain several git commands. Here's the function broken down so it's easier to read:

f() {
  if [ -z \"$1\" ] ; then
    echo 'Error: stashonto requires destination branch.\nExample: git stashonto master\nExample: git stashonto -b new-branch 98e7f99e' 
  else
    # stash everything
    (git stash --include-untracked
    # switch branch
    && git checkout $*
    # apply stash (you must 'git stash drop' to delete the stash if everything goes well)
    && git stash apply)
  fi
}
f

Warning: It's not fancy enough to detect whether stash saved anything, so if you don't have any changes to stash it will print "No local changes to save" and then apply your previous stash. That's why I'm using apply instead of pop.

Usage:

# stash changes and apply on master
git stashonto master
# stash changes and apply on new branch 'project' off of commit 98e7f99e
git stashonto -b project 98e7f99e
idbrii
  • 10,975
  • 5
  • 66
  • 107
1

I made this "smart switch" command. Before to switch, it tries to stash uncommitted changes, leaving a mark in the message.
When you are back, it looks for any marked stash associated to that branch and pop it.

https://gist.github.com/mgaitan/d9a3523d79cd5f9fbfd626f646f0560b

I hope it'll be useful for somebody else.

tin_nqn
  • 106
  • 4
-1

GIT >= 2.27.0

Having changes not staged for commit:

git switch other_branch

and now we are on other_branch with those changes.

suside
  • 609
  • 8
  • 8