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?
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With