Git loses untracked files during “stash” if there are conficts

Git had a bug from version 2.33 onwards, fixed in 2.35. (Thanks to Richard Laager’s comment for the exact version numbers.)

“Stashing” then “unstashing” untracked files (new files you’ve just created) loses those new files, if any of the existing tracked files has a conflict.

Let me explain. You’re adding a new feature to your codebase (you’ve made changes to some files, and you’ve added some new files). You see a bug, and want to fix it right away as a separate commit. So you “stash” everything (using -u to include not only changed files, but also new untracked ones). You implement your bug fix, and commit it. You then “unstash” your files to continue working on your feature. Some of the files you’ve changed have a confict, and are marked as such. What about the new files you’d created before the “stash” (that, by definition, don’t have any conflicts)? In the old version of Git they’d be back in your directory as well, but in the new version of Git they’re just gone.

It’s a shame I upgraded Git yesterday. But it’s good I don’t rely on Git alone. Thanks to Apple’s Time Machine I avoided losing a few hours of work this morning.

Try it out yourself with the following commands:

# Create a Git repo with a single file committed
git init
echo contents > original-file.txt
git add original-file.txt
git commit -m "Creating the file"

# Create a new file, modify an old one, stash
echo foo > new-file.txt
echo contents2 > original-file.txt
git stash push -u

# Modify the old file in a different way, commit
echo contents3 > original-file.txt
git commit -am "Altering the file"

# Apply the stash, see conflict, but what about the new file? 
git stash pop
cat new-file.txt

Using Git 2.24 the original-file.txt is in conflict and new-file.txt is there. Using Git 2.33 the original-file.txt is in conflict, but new-file.txt is gone.

At least on macOS Catalina you can use an older version of git by using /usr/bin/git as opposed to the /usr/local/bin/git installed by Brew.

alias git=/usr/bin/git

I don’t know if this is a bug or an intended feature. I can’t believe it’s an intended feature (why would you want to lose data like this?) but on the other hand I’m sure they have a process they follow to release Git, it seems unlikely something like this would slip through. I have done a quick web search but didn’t find anyone talking about this, which surprised me.

P.S. I recently created a nerdy privacy-respecting tool called When Will I Run Out Of Money? It's available for free if you want to check it out.

This article is © Adrian Smith.
It was originally published on 3 Nov 2021
More on: FAIL | VCS