336

Alright, lets say one day we make happen to make a bunch of modifications and when we go to commit them we notice we were working on the wrong branch.

How can we force git to switch branches without discarding local changes.

I'm probably going to go about this in a naive way while I wait a reply, but I would like to know if theres a correct procedure as I'd be lying if I said this hasn't happened to me before...

  • Backup changed repo
  • git reset --hard
  • git checkout right-branch
  • Restore changes
  • git commit -m "changes"
megawac
  • 10,953
  • 5
  • 40
  • 61

6 Answers6

536

There are a bunch of different ways depending on how far along you are and which branch(es) you want them on.

Let's take a classic mistake:

$ git checkout master
... pause for coffee, etc ...
... return, edit a bunch of stuff, then: oops, wanted to be on develop

So now you want these changes, which you have not yet committed to master, to be on develop.

  1. If you don't have a develop yet, the method is trivial:

    $ git checkout -b develop
    

    This creates a new develop branch starting from wherever you are now. Now you can commit and the new stuff is all on develop.

  2. You do have a develop. See if Git will let you switch without doing anything:

    $ git checkout develop
    

    This will either succeed, or complain. If it succeeds, great! Just commit. If not (error: Your local changes to the following files would be overwritten ...), you still have lots of options.

    The easiest is probably git stash (as all the other answer-ers that beat me to clicking post said). Run git stash save or git stash push,1 or just plain git stash which is short for save / push:

    $ git stash
    

    This commits your code (yes, it really does make some commits) using a weird non-branch-y method. The commits it makes are not "on" any branch but are now safely stored in the repository, so you can now switch branches, then "apply" the stash:

    $ git checkout develop
    Switched to branch 'develop'
    $ git stash apply
    

    If all goes well, and you like the results, you should then git stash drop the stash. This deletes the reference to the weird non-branch-y commits. (They're still in the repository, and can sometimes be retrieved in an emergency, but for most purposes, you should consider them gone at that point.)

The apply step does a merge of the stashed changes, using Git's powerful underlying merge machinery, the same kind of thing it uses when you do branch merges. This means you can get "merge conflicts" if the branch you were working on by mistake, is sufficiently different from the branch you meant to be working on. So it's a good idea to inspect the results carefully before you assume that the stash applied cleanly, even if Git itself did not detect any merge conflicts.

Many people use git stash pop, which is short-hand for git stash apply && git stash drop. That's fine as far as it goes, but it means that if the application results in a mess, and you decide you don't want to proceed down this path, you can't get the stash back easily. That's why I recommend separate apply, inspect results, drop only if/when satisfied. (This does of course introduce another point where you can take another coffee break and forget what you were doing, come back, and do the wrong thing, so it's not a perfect cure.)


1The save in git stash save is the old verb for creating a new stash. Git version 2.13 introduced the new verb to make things more consistent with pop and to add more options to the creation command. Git version 2.16 formally deprecated the old verb (though it still works in Git 2.23, which is the latest release at the time I am editing this).

torek
  • 448,244
  • 59
  • 642
  • 775
  • 4
    What if I want to switch to another branch without committing to current branch (e.g. changes are not finished) and later switch back to carry on? – dragonfly02 Nov 08 '17 at 12:24
  • @stt106: you must still commit, but you can do it, as in this and the other answers, via `git stash` so that the commits—for `git stash`, you get *two* commits per stash entry, in an unusual arrangement—are on *no* branch. Except for very short term special cases, though, I generally prefer making a normal commit. You can `git reset --soft` or `git reset --mixed` later, or use `git commit --amend` to shove it aside, when you're back to working on that branch. (In modern Git, you can also use `git worktree add`, which may be an even-better solution.) – torek Nov 08 '17 at 15:45
  • "This will either succeed, or complain.". Which would be the reasons for success or error when doing the checkout? – nanocv Mar 13 '19 at 09:33
  • 1
    @nanocv: see https://stackoverflow.com/questions/22053757/checkout-another-branch-when-there-are-uncommitted-changes-on-the-current-branch – torek Mar 13 '19 at 15:13
  • @MukulMunjal: `git stash` means *make some commits, then **take my changes away** because they're safely saved in the stash commits*. So of course they're gone after you stash them: that's the *point* of stashing them, to get rid of them, while also saving them. You have to subsequently *un*-stash them, using `git stash apply`. In between these two steps, you can switch branches all you like. – torek May 17 '20 at 10:00
  • @torek - are you suggesting that `git` could be bugged by the paragraph: *So it's a good idea to inspect the results carefully before you assume that the stash applied cleanly, even if Git itself did not detect any merge conflicts.*? – Shuzheng Jun 09 '20 at 09:08
  • @Shuzheng: it's not a question of *bugs* per se. It's that `git merge` is not omniscient: it follows simple text processing rules. Usually those rules lead to the desired result. Sometimes they do not. If you run `git stash pop`, the stash commits are lost and it's hard to get them back if you want to try applying them to a different commit that might produce a better result, for instance. – torek Jun 09 '20 at 13:00
  • Watch out, an untracked file (recently added files and uncommited) might be lost at first git stash https://stackoverflow.com/questions/12147042/lost-git-stash-changes so creating a new branch is failsafe. – Alsushi Sep 07 '20 at 07:43
  • @Alsushi: in general, `git stash` is supposed to leave untracked files alone, and other operations should warn you to move them out of the way first. However, listing a file in `.gitignore` when it *is* in the index (is tracked) leaves Git with permission to clobber the file in some cases, including this one. The file will be saved in the stash, though. – torek Sep 07 '20 at 08:20
  • You need to commit & push local changes to current branch before `git stash`. I lost all my local changes before `git stash`, luckily Pycharm history helped after recreating files. Better as said to make normal commit, then use `git reset --soft` or `git reset --mixed` later – Brian Nov 10 '20 at 14:34
  • 1
    @Brian: `git stash` just makes commits. There have been bugs introduced into `git stash` in several versions of Git, though, and in general I now advise *avoiding* `git stash` entirely if possible. – torek Nov 11 '20 at 07:13
  • I agree with you 100% @torek – Brian Nov 17 '20 at 08:40
  • tldr; don't get coffee breaks :D – fbence Apr 17 '21 at 08:28
  • @rodi: don't like my answer? I'll refund all the money you paid for it! – torek May 22 '21 at 23:06
  • torek It's a constructive suggestion, don't take it personal :) I hope that nobody, people working on your team included, lose money or time because they lose their work. @Ray answer is much more functional and aligned with SO principles. – M4rk May 25 '21 at 01:30
84

Use git stash

git stash

It pushes changes to a stack. When you want to pull them back use

git stash apply

You can even pull individual items out.

To completely blow away the stash:

git stash drop
p0358
  • 139
  • 1
  • 8
Ray
  • 40,256
  • 21
  • 101
  • 138
44

You can use:

  1. git stash to save your work
  2. git checkout <your-branch>
  3. git stash apply or git stash pop to load your last work

Git stash is extremely useful when you want to temporarily save undone or messy work, while you want to do something on another branch.

git -stash documentation

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Andy Winarko
  • 645
  • 1
  • 9
  • 20
  • 1
    The is the most eloquent solution to the problem -- not only in the implicit logic... but in that it's also so easy to remember! – Ahi Tuna Apr 05 '22 at 00:00
27
  • git stash to save your uncommited changes
  • git stash list to list your saved uncommited stashes
  • git stash apply stash@{x} where x can be 0,1,2..no of stashes that you have made
brokenfoot
  • 11,083
  • 10
  • 59
  • 80
12

You could use --merge/-m git checkout option: git checkout -m <another-branch>

-m --merge

When switching branches, if you have local modifications to one or more files that are different between the current branch and the branch to which you are switching, the command refuses to switch branches in order to preserve your modifications in context. However, with this option, a three-way merge between the current branch, your working tree contents, and the new branch is done, and you will be on the new branch.

Source: https://git-scm.com/docs/git-checkout

sergey.n
  • 1,672
  • 19
  • 18
  • And try just plain `git checkout thatbranch` first, which works if it's completely safe, if none of your changes touch files updated by checkout at all. – jthill Jan 22 '21 at 18:10
  • 1
    @sergey.n I think yours is the correct answer. Stashing doesn't always work, it has problems with submodules, staging, and if you're on a branch with no commits stashing straight up will not work. However, you can always merge changes into a new branch. – Jeff Hykin May 02 '21 at 20:41
  • **For beginners reading comments section** : to avoid accidently ending up in detached HEAD with **git checkout** , better use the following synopsis : `$ git switch -c --merge` – projektorius96 Jun 07 '22 at 22:45
  • @Amun which version of bash, dash or relevant shell for git are you using right now ? Seem like shell of your choice does not recognize i.e. acknowledges such command existence . As far as I remember git switch came to action since git version 2.23 or later . If your shell is lower than the version, it might be a case why you get the error ? Let me know . – projektorius96 Nov 16 '22 at 15:24
  • 1
    @projektorius96 I feel so dumb but my server git was way out of date. Sorry and thanks for the answer. Feel free to delete as this wont probably help anyone else – Amund Nov 18 '22 at 22:05
6

You can either :

  • Use git stash to shelve your changes or,

  • Create another branch and commit your changes there, and then merge that branch into your working directory

X3074861X
  • 3,709
  • 5
  • 32
  • 45