{"action":"created","issue":{"url":"https://api.github.com/repos/libgit2/libgit2/issues/2912","labels_url":"https://api.github.com/repos/libgit2/libgit2/issues/2912/labels{/name}","comments_url":"https://api.github.com/repos/libgit2/libgit2/issues/2912/comments","events_url":"https://api.github.com/repos/libgit2/libgit2/issues/2912/events","html_url":"https://github.com/libgit2/libgit2/issues/2912","id":57999129,"number":2912,"title":"git_stash_save() doesn't behave like Git CLT for index-deleted but workdir-modified files","user":{"login":"swisspol","id":627915,"avatar_url":"https://avatars.githubusercontent.com/u/627915?v=3","gravatar_id":"","url":"https://api.github.com/users/swisspol","html_url":"https://github.com/swisspol","followers_url":"https://api.github.com/users/swisspol/followers","following_url":"https://api.github.com/users/swisspol/following{/other_user}","gists_url":"https://api.github.com/users/swisspol/gists{/gist_id}","starred_url":"https://api.github.com/users/swisspol/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/swisspol/subscriptions","organizations_url":"https://api.github.com/users/swisspol/orgs","repos_url":"https://api.github.com/users/swisspol/repos","events_url":"https://api.github.com/users/swisspol/events{/privacy}","received_events_url":"https://api.github.com/users/swisspol/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":2,"created_at":"2015-02-17T23:24:17Z","updated_at":"2015-02-17T23:36:19Z","closed_at":null,"body":"This one is for @ethomson I guess :)\r\n\r\nI was perusing the implementation of `git_stash_save()` and especially `commit_worktree()` and how it uses `git_diff_tree_to_workdir_with_index()` which has a peculiar behavior and was wondering if Git CLT really does this. Turns out it does not, so libgit2's stashing currently does not match Git CLT.\r\n\r\nPrepare a dead simple test repo like this to have a deleted-in-index-but-modified-in-workdir file:\r\n```sh\r\n$ git init\r\nInitialized empty Git repository in /private/tmp/stash/.git/\r\n$ echo \"Hello world\" > hello.txt\r\n$ echo \"Bonjour monde\" > bonjour.txt\r\n$ git add -A\r\n$ git commit -m \"Initial commit\"\r\n[master (root-commit) c04b8cb] Initial commit\r\n 2 files changed, 2 insertions(+)\r\n create mode 100644 bonjour.txt\r\n create mode 100644 hello.txt\r\n$ git rm hello.txt \r\nrm 'hello.txt'\r\n$ echo \"TEST\" > hello.txt\r\n$ echo \"Au revoir monde\" > bonjour.txt \r\n$ git status\r\nOn branch master\r\nChanges to be committed:\r\n  (use \"git reset HEAD <file>...\" to unstage)\r\n\r\n\tdeleted:    hello.txt\r\n\r\nChanges not staged for commit:\r\n  (use \"git add <file>...\" to update what will be committed)\r\n  (use \"git checkout -- <file>...\" to discard changes in working directory)\r\n\r\n\tmodified:   bonjour.txt\r\n\r\nUntracked files:\r\n  (use \"git add <file>...\" to include in what will be committed)\r\n\r\n\thello.txt\r\n```\r\n\r\nStash with Git CLT and notice how the deleted-in-index-but-modified-in-workdir file is stashed as a **modified** file:\r\n```\r\n$ git stash\r\nSaved working directory and index state WIP on master: 1b971ca Initial commit\r\nHEAD is now at 1b971ca Initial commit\r\n\r\n$ git diff-index stash\r\n:100644 100644 682672c4f6391ec89dbb7ae0a4070058df0c2a66 2fd81b86452753fd74b59d93d62ffe562811a8e2 M\tbonjour.txt\r\n:100644 100644 2a02d41ce21323b1cdc228c78cec2f81c054bd34 802992c4220de19a90767f3000a79a31b98d0df7 M\thello.txt\r\n\r\n$ git stash pop\r\nOn branch master\r\nChanges not staged for commit:\r\n  (use \"git add <file>...\" to update what will be committed)\r\n  (use \"git checkout -- <file>...\" to discard changes in working directory)\r\n\r\n\tmodified:   bonjour.txt\r\n\tmodified:   hello.txt\r\n\r\nno changes added to commit (use \"git add\" and/or \"git commit -a\")\r\nDropped refs/stash@{0} (9d7d6466523528527b8b6090e9de4437fe857961)\r\n```\r\n\r\nNow try the same with `git_stash_save()` and notice how the deleted-in-index-but-modified-in-workdir file is stashed as a **deleted** file:\r\n```sh\r\n# CALL git_stash_save() here\r\n$ git status\r\nOn branch master\r\nnothing to commit, working directory clean\r\n\r\n$ git diff-index stash\r\n:100644 100644 682672c4f6391ec89dbb7ae0a4070058df0c2a66 2fd81b86452753fd74b59d93d62ffe562811a8e2 M\tbonjour.txt\r\n:000000 100644 0000000000000000000000000000000000000000 802992c4220de19a90767f3000a79a31b98d0df7 A\thello.txt\r\n\r\n$ git stash pop\r\nRemoving hello.txt\r\nOn branch master\r\nChanges not staged for commit:\r\n  (use \"git add/rm <file>...\" to update what will be committed)\r\n  (use \"git checkout -- <file>...\" to discard changes in working directory)\r\n\r\n\tmodified:   bonjour.txt\r\n\tdeleted:    hello.txt\r\n\r\nno changes added to commit (use \"git add\" and/or \"git commit -a\")\r\nDropped refs/stash@{0} (ec1ca1be2486bbe74fd81b2953eb57bf22a53d0b)\r\n```"},"comment":{"url":"https://api.github.com/repos/libgit2/libgit2/issues/comments/74779572","html_url":"https://github.com/libgit2/libgit2/issues/2912#issuecomment-74779572","issue_url":"https://api.github.com/repos/libgit2/libgit2/issues/2912","id":74779572,"user":{"login":"swisspol","id":627915,"avatar_url":"https://avatars.githubusercontent.com/u/627915?v=3","gravatar_id":"","url":"https://api.github.com/users/swisspol","html_url":"https://github.com/swisspol","followers_url":"https://api.github.com/users/swisspol/followers","following_url":"https://api.github.com/users/swisspol/following{/other_user}","gists_url":"https://api.github.com/users/swisspol/gists{/gist_id}","starred_url":"https://api.github.com/users/swisspol/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/swisspol/subscriptions","organizations_url":"https://api.github.com/users/swisspol/orgs","repos_url":"https://api.github.com/users/swisspol/repos","events_url":"https://api.github.com/users/swisspol/events{/privacy}","received_events_url":"https://api.github.com/users/swisspol/received_events","type":"User","site_admin":false},"created_at":"2015-02-17T23:36:19Z","updated_at":"2015-02-17T23:36:19Z","body":"I patched my fork of libgit2 to use `git_diff_tree_to_workdir()` instead and now the behavior matches Git CLT which is what one would expect."}}