git mv file1 file2 git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # renamed: file1 -> file2 git stash git stash pop # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # new file: file2 # # Changes not staged for commit: # (use "git add/rm <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working directory) # # deleted: file1
As you can see, git loses the renamed relationship after a stash / pop. Is there any way to regain this relationship, or have stash know that files were moved? I often stash to see what my system state is like pre-changes, but having it lose the rename relationship is a problem for me. I don't know how to fix it other than deleting the new file, doing a git mv again, and replacing the new file's contents.
But if a git stash pop conflict arises, then the problematic files won't be added to the index. Instead, Git populates the conflicted files with content from both the local working tree and the stash. The stash entry is kept in case you need it again. There's no magic remedy for such merge conflicts.
Retrieve the Stashed File Here, the “ls” command is used to show the list of files and folder of the repository folder, and the “git stash apply” command is used to restore the untracked files.
If you made two stashes, then just call git stash pop twice. As opposed to git stash apply , pop applies and removes the latest stash.
When a developer uses the git stash apply command, the most recently saved stash overwrites files in the current working tree but leaves the stash history alone. In contrast, the pop command restores files but then deletes the applied stash.
If you haven't already popped your stash, do:
git stash pop --index
This correctly preserves moved (but not committed) file relationships in a stash. According to git help stash
:
If the --index option is used, then tries to reinstate not only the working tree's changes, but also the index's ones. However, this can fail, when you have conflicts (which are stored in the index, where you therefore can no longer apply the changes as they were originally).
If you've already popped your stash and want to re-create the moved relationship, do:
git rm --cached file1
This removes the "old" unmoved file from the index:
Use this option to unstage and remove paths only from the index
Short answer: git rm --cached file1
All git mv
really does is rename the file (on the filesystem) and then add a file deletion and creation to the index (staging area). It's not specially marked. Other machinery subsequently realizes that it was a rename, by seeing that the content that was called file1 before is now called file2.
Since git stash
commands modify the index, they can perturb things. Note that now you have the creation staged, but not the deletion! (Normally git-stash leaves everything unstaged after a pop, but in this case I think it doesn't have much choice but to put the new file in the index, to avoid you having no idea which one to keep. You can avoid this ever happening with git stash pop --index
, but that bombs out if the stashed changes can't be cleanly applied, so it's not default.) git status
can't possibly show it as a rename anymore, because the rename is effectively split between the index and the work tree, and neither section can fully claim it.
Simply run git rm --cached file1
to stage the deletion (i.e. remove file1 from the index) and it will show up as a rename again. You could also run git add -u
to automatically add changes, as long as you have no other changes that you don't want to stage.
Note that this means that in practice you don't need to worry: when you properly stage everything in preparation to commit (e.g. with git add -u
), the "problem" takes care of itself.
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