{"thread":{"id":"44328","subject":"[BUG] git-stash fails when tracked file is replaced with directory","startedAt":"2016-10-19T15:34:30Z","lastAt":"2016-10-19T15:34:30Z","messageCount":1,"participants":["Alex C. Reed, IV"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"304391","messageId":"CAGDUdtnUT+_G9bHOYVw_5i-+r9vJHFSjP=Zg2HzA=cQfOkKfwA@mail.gmail.com","threadId":"44328","inReplyTo":null,"subject":"[BUG] git-stash fails when tracked file is replaced with directory","fromName":"Alex C. Reed, IV","fromEmail":"acreed4@gmail.com","sentAt":"2016-10-19T15:34:09Z","receivedAt":"2016-10-19T15:34:30Z","isPatch":false,"sender":{"key":"acreed4@gmail.com","avatar":null},"body":"When a file is deleted from Git and replaced with a directory+file(s),\ngit-stash has two unexpected behaviors.  This is tested against\nversions 2.8.1 and 2.10.1:\n\n\n1) Old file is removed from index and newly-added directory+file(s)\nare added to index.\nIn this scenario, 'git stash' fails with the message:\n\n    error: <directory>: is a directory - add individual files instead\n    fatal: Unable to process path <directory>\n    Cannot save the current work tree state\n\nThe expected result would be that Git properly records the state\ncurrently stored in index.\n\n\n2) Old file is removed and new-added directory+file(s) are present\nonly in worktree, but not added to the index.\nIn this scenario, 'git stash -u' works fine, but 'git stash apply'\nfails with the message:\n\n    fatal: cannot create directory at '<directory>': File exists\n    Could not restore untracked files from stash\n\nThe expected result would be that Git removes 'file' and replaces with\nthe untracked contents recorded in the original stash.\n\n\nIt is worth noting that Git does properly handle the scenario where\nthe stash operation of (1) is replaced with a commit to a temporary\nbranch, so this quirk seems to be restricted to stashes only.\n\n\nI found a similar issue reported 22 April 2016 titled \"possible bug of\ngit stash deleting uncommitted files in corner case\".  The thread-view\nof the message is here:\n\n    http://marc.info/?t=146132568600002&r=1&w=2\n\n\nHere's a quick-and-dirty bash script to re-create all three scenarios\n(1, 2, and 'commit to branch'):\n\n===== BEGIN stash-test.sh\n#!/bin/bash\n\nset -x\nexport GIT_TRACE=1\n\nsetup() {\n  repo=$1\n\n  # Prepare repo\n  rm -rf $repo\n  git init $repo\n  cd $repo\n\n  # Add initial file (symlink to external assets)\n  ln -fs /external/dir dir\n  git add dir\n  git commit -m \"Add symlink to /external/dir\"\n\n  # Replace symlink with local copy of assets\n  rm dir\n  mkdir -p dir\n  touch dir/local_copy_of_dir_files\n}\n\n{\n  ( setup stash-test-unstaged\n    git stash -u\n    git stash apply )\n\n  ( setup stash-test-staged\n    git add .\n    git stash )\n\n  ( setup stash-test-commit\n    git add .\n    git co -b stash-branch\n    git commit -m \"commit to branch instead of stash\" )\n\n} 2>&1 | tee stash-test.log\n===== END stash-test.sh\n\n\nThanks,\n-Alex Reed\n"}]}