Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rebasing from stash, strange result

Tags:

git

I'm just asking this out of curiosity. There are other ways to deal with this kind of situation in real life, but I find the following behavior of git a bit strange.

Summary: Stashing creates, behind the curtain, two commits, one contains the index and the other the non-added edits. If we checkout the latter and try to rebase it, we somehow only get the changes from the index. Why is that?

Detailed example follows:

First let's make a repo with one commit, then one more edit that is added to index, then one more edit that is not added to index, and then stash:

git init
echo 1 > a.txt
git add a.txt
git commit -m"First commit"
echo 2 >> a.txt
git add a.txt
echo 3 >> a.txt
git stash
git log --all --graph --oneline

  *   5c00fc0 WIP on master: c8af537 First commit
  |\  
  | * 965c986 index on master: c8af537 First commit
  |/  
  * c8af537 First commit

So git stash seems to save both the index and the non-added edit as commits with their own hashes (in my case, 965c986 for index and 5c00fc0 for the non-added edits).

Now edit a new file and commit:

echo x >> b.txt
git add b.txt
git commit -m"Second commit"

So all of the commits now look like:

git log --all --graph --oneline

  * b589f50 Second commit
  | *   5c00fc0 WIP on master: c8af537 First commit
  | |\  
  |/ /  
  | * 965c986 index on master: c8af537 First commit
  |/  
  * c8af537 First commit

Say, we now want to take the stashed edits and combine them with the second commit. There are other ways to do this (like git stash apply, but what if we already had cleaned the stash, and then digged the commit from the reflog), but let's just try with:

git checkout 5c00fc0
[warning message here]
cat a.txt
  1
  2
  3
git rebase master
  First, rewinding head to replay your work on top of it...
  Applying: index on master: c8af537 First commit

But now, the resulting file a.txt is just:

cat a.txt 
  1
  2

This is the whole graph:

git log --all --graph --oneline
  * 5fc3ade index on master: c8af537 First commit
  * b589f50 Second commit
  | *   5c00fc0 WIP on master: c8af537 First commit
  | |\  
  |/ /  
  | * 965c986 index on master: c8af537 First commit
  |/  
  * c8af537 First commit

So it looks like, even though we checked out commit 5c00fc0, the rebase only applied the changes from the commit 965c986, i.e. the edits that were in the index when we stashed. But whatever was in 5c00fc0 has been ignored.

Question: Why is that? Is there some some reasonable explanation for this behavior? Or should this be considered a bug?

like image 695
Sampo Smolander Avatar asked Jul 25 '13 04:07

Sampo Smolander


People also ask

What is stash rebase?

git stash, which makes a temporary, local save of your code git reset, which lets you tidy up your code before doing a commit git bisect, a function that allows you to hunt out bad commits git squash, which allows you to combine your commits git rebase, which allows for applying changes from one branch onto another.

How do I get my stash changes back?

To retrieve changes out of the stash and apply them to the current branch you're on, you have two options: git stash apply STASH-NAME applies the changes and leaves a copy in the stash. git stash pop STASH-NAME applies the changes and removes the files from the stash.

What does stashing changes mean in git?

git stash temporarily shelves (or stashes) changes you've made to your working copy so you can work on something else, and then come back and re-apply them later on.

How do you pop stash changes?

Retrieving stashed changes You can reapply stashed changes with the commands git stash apply and git stash pop . Both commands reapply the changes stashed in the latest stash (that is, stash@{0} ). A stash reapplies the changes while pop removes the changes from the stash and reapplies them to the working copy.


1 Answers

Turns out, git just (by default) ignores merge commits when rebasing. And stashing creates the WIP commit and the index commit, and the WIP commit is a merge, since it has both the index commit and the c8af537 as parents.

Nothing to do with stashing as such.

like image 161
Sampo Smolander Avatar answered Dec 08 '22 22:12

Sampo Smolander