How do I merge my local uncommitted changes into another Git branch?

Viewed 147435

How can I do the following in Git?

My current branch is branch1 and I have made some local changes. However, I now realize that I actually meant to be applying these changes to branch2. Is there a way to apply/merge these changes so that they become local changes on branch2 without committing them on branch1?

7 Answers

Since your files are not yet committed in branch1:

git stash
git checkout branch2
git stash pop

or

git stash
git checkout branch2
git stash list       # to check the various stash made in different branch
git stash apply x    # to select the right one

Above is the longer more explicit version of rbento's answer:

git stash
git stash branch branch2

It uses:

git stash branch <branchname> [<stash>]

  • Creates and checks out a new branch named <branchname> starting from the commit at which the <stash> was originally created,
  • applies the changes recorded in <stash> to the new working tree and index.

If that succeeds, and <stash> is a reference of the form stash@{<revision>}, it then drops the <stash>.

This is useful if the branch on which you ran git stash push has changed enough that git stash apply fails due to conflicts.
Since the stash entry is applied on top of the commit that was HEAD at the time git stash was run, it restores the originally stashed state with no conflicts.


As commented by benjohn (see git stash man page):

To also stash currently untracked (newly added) files, add the argument -u, so:

git stash -u

Stashing, temporary commits and rebasing may all be overkill. If you haven't added the changed files to the index, yet, then you may be able to just checkout the other branch.

git checkout branch2

This will work so long as no files that you are editing are different between branch1 and branch2. It will leave you on branch2 with you working changes preserved. If they are different then you can specify that you want to merge your local changes with the changes introduced by switching branches with the -m option to checkout.

git checkout -m branch2

If you've added changes to the index then you'll want to undo these changes with a reset first. (This will preserve your working copy, it will just remove the staged changes.)

git reset

If it were about committed changes, you should have a look at git-rebase, but as pointed out in comment by VonC, as you're talking about local changes, git-stash would certainly be the good way to do this.

These are the steps I follow:

  • git clone {link}
  • cd {repo folder}

You can check the status and which branch you are on using:

  • git status
  • git branch
  • git branch -a

Note: Here if you make changes in your local repo before moving to the new branch, the following steps should still work.

If "git branch" shows master, and you want to create+move to another branch:

  • git checkout -b {branch name}

Check branch again using "git branch" It should now show that you are in the new branch.

Now add, commit and push:

  • git add .
  • git commit -m "added new branch"
  • git push origin {branch name}

The above steps work for me in both the situation when I have made changes before moving to the new local branch or making changes after moving to the new branch. I hope it helps people running into similar situations.

If the uncommitted changes are a mix of untracked and tracked changes

What are untracked changes?

When you created e.g a new file. VSCode e.g displays a U next to the file in the file explorer.

What are tracked changes?

When you make changes to files that were committed to the repo earlier (in previous commits).

Quick explanation of procedure

So imagine you are on branch A, but you want to commit only changes to existing files to branch A, while the newly created file (untracked) should be committed to a new branch B. It's possible to use stashing with a few tricks, explained step by step.

Add script to .git/config

Inside the .git folder there is a config file. Open it up and you will see something like this:

[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
    ignorecase = true
    precomposeunicode = true
[remote "origin"]
    url = https://github.com/...
    fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
    remote = origin
    merge = refs/heads/main

change the config file to:

[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
    ignorecase = true
    precomposeunicode = true
[alias]
    stash-untracked = "!f() {    \
                git stash;               \
                git stash -u;            \
                git stash pop stash@{1}; \
            }; f"
[remote "origin"]
    url = https://github.com/...
    fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
    remote = origin
    merge = refs/heads/main

Now you will be able to use the following command while you are on branch A.

git stash-untracked

You will see that the new file disappeared, if you are using a editor like VSCode (it's now stashed)

While still on branch A stage and commit the changes to the existing files:

git add .
git commit -m "committing tracked changes to current branch"

Next step is creating a new branch B (with checkout -b you visit it immediately)

git checkout -b newBranchName

When using stash pop the stashed changes get added to your current branch.

git stash pop

The only thing left is to stage and commit the changes on the new branch B

git add .
git commit -m "created new file"
Related