git/list[1] front-page[2] threads[3] people[4] search[5] about
 

bug: git pull may delete untracked files in submodule without notice

From
CSChristian Spanier <cspanier@boxie.eu>
Date
May 3, 2019, 08:02 UTC
Message-ID
<2e321dbe-42a3-7516-52aa-4bc50a3c403e@boxie.eu>
Hi,

I found a bug where Git may delete untracked files without notice in certain situations. This bug effects Git 2.21.0 both on Linux and Windows. In summary this happens when git pull merges a commit that replaces a submodule folder with a symlink. Any files within the folder are deleted without notice. Check out the script below for details.

This happend on some developer's machine and deleted a repository containing about 200GiB of files and tons of uncommited local scripts, log files and whatever, just because some other dev accidentally commited a temporary change.

Greetings, Christian Spanier

##### PREPARATION #####

# New empty repository #1 mkdir rep1 cd rep1 git init --bare . cd ..

# New empty repository #2 mkdir rep2 cd rep2 git init --bare . cd ..

# Clone repository #1 and create initial commit git clone rep1 clone_rep1_user1 cd clone_rep1_user1 touch README git add README git commit -m "initial commit" git push cd ..

# Clone repository #2 and create initial commit git clone rep2 clone_rep2 cd clone_rep2 touch README git add README git commit -m "initial commit" git push cd ..

# Add repository #2 as a submodule to repository #1 cd clone_rep1_user1 git submodule add ../rep2 git commit -m "add submodule" git push cd ..

# User 2 also clones repository #1 and #2 recursively git clone --recursive rep1 clone_rep1_user2

# User 2 starts working in his folder and adds an important local file which is # not yet committed inside the submodule folder. cd clone_rep1_user2/rep2 echo "important work" > uncommitted_file cd ../../

# Meanwhile, user 1 temporarily switch out folder /clone_rep1_user1/rep2 with a # symbolic link to a different folder (for whatever reason, maybe a copy of an # older version or anything). mkdir rep2_alternative cd clone_rep1_user1 mv rep2 ../rep2_backup ln -s ../rep2_alternative rep2 # On Windows this can be done with 'mklink /D rep2 ../rep2_alternative', # which requires admin privileges. The bug is not reproducible when # using a directory junction with 'mklink /D /J ...'.

# He does some work on rep1 but then accidently adds the symbolic link to his # next commit and pushes the changes. Notice the typechange of rep2. echo "some" > work git status # On branch master # Your branch is up to date with 'origin/master'. # # Changes not staged for commit: # (use "git add <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working directory) # # typechange: rep2 # # Untracked files: # (use "git add <file>..." to include in what will be committed) # # work # # no changes added to commit (use "git add" and/or "git commit -a") git add . git commit -m "do some work" git push cd ..

# NOW THE BUG:

# User 2 pulls the changes and loses his important work in # rep2/uncommitted_file because Git replaces the folder with a symlink # without checking for modified or uncommited files! # He should get an error in this case! cd clone_rep1_user2 git pull cat rep2/uncommitted_file # cat: rep2/uncommitted_file: Not a directory # "important work" in rep2/uncommitted_file is gone :(

Next: Duy Nguyen
Message 1 of 3 in “bug: git pull may delete untracked files in submodule without notice”
  1. Christian SpanierMay 3, 2019
  2. Duy NguyenMay 3, 2019
  3. Phillip WoodMay 3, 2019

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.