Simon
Simon

Reputation: 2538

Create new branch keeping unstaged changes in Master

I'm fairly inexperienced with Git outside of the normal committing process.

Right now I'm on the master branch and I have 8 unstaged changes. What I'd like to do is create a new branch with the last commit (i.e without the 8 unstaged changes) but I want to keep the unstaged changes saved so that I can revisit them later.

How would I do this?

Upvotes: 2

Views: 1711

Answers (3)

Matthew
Matthew

Reputation: 1617

As others have mentioned in answers and comments there are at least three options. There's a fair bit of overlap between them and each has pros and cons:

  1. Create new branches (plural)
  2. Stash the changes
  3. Add a working tree (worktree)

Create New Branches

Branches cost practically nothing so the simplest option, with no real change to your existing workflow, is to create new branches. If you're ever in doubt if you'll want something some day it generally doesn't hurt to commit it to a "work-in-progress" or "experimental" branch.

In your particular scenario I would recommend creating a new branch to save your 8 unstaged changes (let's call them experimental) and another new branch off master for the other work you want to do (let's call it a new feature):

git checkout -b experimental/foo
git add --all
git commit -m 'Trying a new structure for Foo'
git checkout master
git checkout -b feature/bar

I would recommend this approach if you want to save your 8 changes for a while (or if you're not sure how soon you'll come back to them). You can even push the experimental branch to your upstream repository for additional redundancy or to collaborate on it.

Note 1 The last two commands can be combined into one line git checkout -b feature/bar master. It's cleverer (and arguably more explicit) but I like to keep things simple and always checkout a branch before creating a new branch from it

Note 2 The "experimental/" and "feature/" namespaces are optional but I find them helpful for future me to know what past me was thinking. And write a good commit message, future you will thank past you :)

Stash the Changes

Another option is to temporarily "stash" the changes and then later re-apply the stashed changes to your master branch (or even some other branch).

In your situation, I would stash the changes (with a descriptive message), create the new feature branch and then, at a later point, you can come back and apply the stashed changes to master:

git stash --include-untracked save 'Trying a new structure for Foo'
git checkout -b feature/bar
...
<make a few changes in feature/bar and commit or discard them>
...
git checkout master
git stash apply

Stashing is a little more complicated but it can be quite flexible. The main difference to creating a branch is that stashes are local only; they can't be pushed upstream. I would only recommend this option if you know you need the extra flexibility stashing provides or if the stash will only be very short lived, basically a quick cut and paste.

Note 1 By default stashing only includes modified files, the --include-untracked option is important if your changes include any new files. You can also use --all (like we used with git add above) but that will also stash ignored files.

Note 2 The above assumes you didn't stash anything else in the meantime. Use git stash list to check you haven't made other stashes since. Once you're finished with this stash you can use git stash drop to delete it. git stash pop let's you apply and drop in a single command.

Note 3 Atlassian has a pretty useful tutorial on how to use git stash if you want to learn more.

Add a Working Tree (Worktree)

Another (slightly) more complicated but flexible option is adding a working tree (from now on I will just use "worktree" to reflect the name of the command). Your worktree is where unstaged changes exist, moving with you as you checkout and move between branches. By default there is only one "main" worktree but you can add one or more "linked" worktrees to let you have multiple branches checked out at the same time and to have different unstaged changes in each worktree.

In the scenario above, I would probably create a new worktree (and branch) based on master and then switch to the new worktree directory. Your unstaged changes will remain in your main worktree and you can go back to work on them simply by changing back to that directory:

git worktree add -b feature/bar ../app-name-bar
cd ../app-name-bar

Because this allows you to have more than one branch checked out at a time, it enables some really nice workflows. For example, you can have two different terminal and/or editor windows/tabs open and look at two branches side by side. This is the solution I would choose for anything except very short term needs for which I'd probably use stashing.

Note 1 Using this option you're also creating a new branch. This is basically a special case of option 1.

Note 2 You can't have the same branch active in two different worktrees. If you need to for some reason you'll need to copy the branch or run the second one detached with --detach (see this article for more info)

Note 3 The above commands will create a new folder "app-name-bar" at the same level as your current repository. So let's say your app is called "todos", you'd end up with another copy of "todos" in your filesystem called "todos-bar" (although you can call it whatever you like). To keep things organised I prefer to create a containing folder for all my worktree folders. The following steps show how to move and rename your current repository from todos to todos/main so you can have one or more additional linked worktrees living alongside your main worktree:

# Do these steps just once
mv todos/ main/
mkdir todos
mv main todos/
cd todos/main

# Do these steps every time you want to add a worktree...
cd todos/main
git worktree add -b feature/bar ../bar
cd ../bar

# ...and you'll end up with this directory structure
# └─ todos/
#   ├─ main/
#   | └─ ...
#   └─ bar/
#     └─ ...

Upvotes: 0

Dhirendra
Dhirendra

Reputation: 790

You can simply do

git checkout -b newbranch

This will create a new branch from master, checkout you to newbranch & you will have your unstaged/uncommited changes as it is.

And if you want to keep the changes while switching between branches but don't want to commit, use git stash

Upvotes: 1

Mureinik
Mureinik

Reputation: 311723

If you haven't committed these new changes, they are invisible to branching, and you can just branch out of master:

$ git branch newbranch

Or, more explicitly:

$ git branch newbranch master

Upvotes: 1

Related Questions