char m
char m

Reputation: 8336

Is it possible to get changes from a branch created from master back to master as local changes?

So if I do in master:

git checkout -b my-branch

and do several commits + pushes there. Then I do:

git checkout master
git pull

Can I now somehow get those changes in my-branch to master as local changes just like using git stash apply after doing git stash?

EDIT: By local changes I mean if I edit something or take from stash the files in workspace are edited, pending changes but they are not committed. Local changes have no commit history or anything. The local files are simply changed. If i commit and push the "local" changes to master there won't be any commit history from my-branch.

Upvotes: 3

Views: 78

Answers (3)

TTT
TTT

Reputation: 28869

One way to achieve this is to simply merge in your branch and then reset mixed right back to where you just were. So, while you're on master, after the pull:

git merge --no-ff --no-edit my-branch
git reset @^1

This works because the merge brings in all of the changes from my-branch, and then the reset (which is mixed by default if you don't specify a type) brings you back to where you were, but with all of the changes from my-branch as pending, just like they would be with git stash apply.

Note @^1 is short for HEAD^1 which means the first parent of the merge commit. Read more about the meaning of caret and tilde here.

Side note: although this works in your scenario, as Matt pointed out in a comment, it wouldn't work if you were able to fast-forward merge the other branch in and that branch had multiple commits. By adding --no-ff to the merge statement, a merge commit will be created regardless, and then this works in the more general case too. Adding --no-edit skips the prompt to write the merge commit message, which you don't need since you're going to throw that commit away in the next command.

Upvotes: 2

Matt
Matt

Reputation: 13923

The command git stash apply takes the stashed changes and applies them on top of the current working tree state. Note that no commit is made or referenced at this point. I assume that by "local changes" you mean such changes in your working tree. This behaviour can be replicated for branches with git restore as follows:

git restore --source=my-branch --worktree -- .

Let's see the two commands in comparison with the following graph:

$ git log --oneline --graph --all
* e7cea52 (my-branch) Same as in stash
| *   b3d1317 (refs/stash) WIP on master: df7538f Initial commit
| |\  
|/ /  
| * 0f7231b index on master: df7538f Initial commit
|/  
* df7538f (HEAD -> master) Initial commit

The proposed solution with git-restore applies the deletion and modification. The new file is added and left untracked (not added to the index):

$ git restore --source=my-branch --worktree -- .
$ git status -s
 D old.txt
 M readme.md
?? new.txt

When using git-stash, the deletion and modification is applied as well. The only difference is that the new file is staged already (added to the index):

$ git stash apply
$ git status -s  
A  new.txt
 D old.txt
 M readme.md

If you want to get the actual commits (not just the changes in the worktree) you can use git merge my-branch as suggested by @joanis.

Upvotes: 3

joanis
joanis

Reputation: 12193

There are several routes you can go here, I'll spell out the two that make the most sense to me.

Assumption: "local changes" is ill defined: do you mean local commits at the tip of master, or local modifications that are not even committed yet? I'm going to assume the former since it makes more sense: you want to bring those commits into branch master.

Option 1: rebase my-branch at the tip of master

If you want the my-branch commits at the tip of master, you need rebase:

git checkout my-branch
git rebase master

Then if you want to continue working on master, merge my-branch in:

git checkout master
git merge my-branch

Option 2: just merge my-branch into master

If you don't mind bubbles in your history, skip the rebase and just merge my-branch into master, with those same two commands:

git checkout master
git merge my-branch

Upvotes: 1

Related Questions