4

Running git status I see a number of files marked deleted:

On branch my-branch
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
    deleted:    nta/executor/.gitignore
    deleted:    nta/executor/NTA_EXECUTOR_README.md
    deleted:    nta/pom.xml
    ...

though these files still exist in the file system. I tried using the suggested method to unstage these changes, for example

git restore --staged nta/executor/.gitignore

This worked on some of the files, but many others remain listed as deleted.

A number of other SO questions describe similar problems:

but the methods described therein have not solved my particular problem. I have tried

git reset <file>
git reset --hard <file>  # fatal: Cannot do hard reset with paths.
git reset -- <file>
git checkout -- <file>

with no luck. Any other ideas?


Additionally

If it helps, here's a description of the probably stupid thing I did to get here:

I wanted to stage a number of files called foo in various directories:

git add */*/foo

This ended up adding many more foos than I expected. So I attempted to backtrack:

git restore --staged  */*/foo

And suddenly a ton of non-foo files were listed as deleted

(and now you know the rest of the story)

Community
  • 1
  • 1
Mike S
  • 1,451
  • 1
  • 16
  • 34
  • The message does not mean the files you can see were deleted. It means the corresponding files in the index (staging area) were marked for deletion. It is telling you what a commit right now would consist of. – matt Apr 04 '20 at 02:07
  • Okay...so how do I unmark them for deletion? – Mike S Apr 04 '20 at 02:56
  • Well I’m not sure. I would have said simple `git reset`. – matt Apr 04 '20 at 02:58
  • So all this “foo” talk is not helpful. You have hidden from us what commands you really gave, and now it turns out you are only revealing a tiny bit of what `git status` tells you. Do you want help or not? – matt Apr 04 '20 at 13:20
  • Where have I hidden the commands I gave? I told you exactly the commands I used. I said `foo` because you gain nothing important by knowing that the files I described are all actually called `part-00000`. I didn't post the entire `git status` output because the files and paths contain names and information I don't want to put in public. I pasted exactly what I thought was relevant. It's my bad that I didn't post the bit about untracked files that I mentioned in another comment – but I hadn't caught that detail when I made the original post, and mentioned it as soon as I discovered it – Mike S Apr 04 '20 at 13:53

2 Answers2

5

Based on comments, it looks like there might be some sort of bug in your version of Git. A simple git reset (with no arguments at all) should have undone the problem, but in fact you had to remove the index file first, then reset:

rm .git/index
git reset

This git reset will re-build the index file from scratch, now that it's missing. This should be unnecessary. (Note also that the location of the index file depends on whether this is an added work-tree from git worktree add; the above assumes it's not.)

(One potential possible cause for this is that Windows has modes in which it refuses to let a program write to a file.1 But that should show up as an error when running git reset. It might also prevent removing the file, in which case rm .git/index would fail too. So it's not at all clear what is going on here.)

Original answer below.


1Windows has something called "mandatory file locks". Programs cannot avoid these locks. Linux in general has only advisory file locking, although there are some Linux file systems that have extra features. See, e.g., How do I make Windows file-locking more like UNIX file-locking?


As matt said in a comment, this means that you've had Git delete the index copy of these files. Therefore, comparing the HEAD commit to the proposed next commit, the difference will be—if you actually commit right now—that those files won't be in the next commit, i.e., between those two commits, you've deleted the files.

To put one file back, follow the instructions that git status printed:

  (use "git restore --staged <file>..." to unstage)

i.e., run:

git restore --staged nta/executor/.gitignore

to copy the HEAD copy of nta/executor/.gitignore back into Git's index. Now the HEAD copy and the index's proposed-next-commit copy match, and git status will no longer mention the file. Repeat for each file as needed.

If you prefer, you can en-masse overwrite the entire index (the entire proposed next commit) from the current commit with:

git reset

(or git reset --mixed, but --mixed is the default).

If you've carefully copied some particular file into the index, this will overwrite that carefully-copied file in the index, and you may have to re-copy it carefully again, to get the effect you so carefully set up. But usually, we tend to copy whatever we have in our work-trees, into the index, so wiping out the index copy this way is not a big deal.

I tried using the suggested method to unstage these changes ... This worked on some of the files, but many others remain listed as deleted.

We could use more detail on this, such as an actual cut-and-paste of the before-and-after git status (or parts of it) and the chosen git restore command. It definitely should go back to the state it had in the HEAD commit, after which git status should be quiet about it.

torek
  • 448,244
  • 59
  • 642
  • 775
  • Thanks for the input. By "using the suggested method" I meant using the `git restore --staged ...` method `git status` suggested. As I mentioned, using this method, the before-and-after git statuses are identical. I also tried a blanket `git reset` and this changed nothing in the `git status` results either. Something I just noticed though is that some of those `foo` files I mentioned above are now listed in `Untracked files` though they were added to the repo many commits ago – Mike S Apr 04 '20 at 12:20
  • An *untracked file* is a file that *is* in your work-tree (the part of the repository where you can see your files), but is *not* in the index. `git status` first compares the current (HEAD) commit to the index: whatever is the same, it says nothing, and whatever is different, it tells you that the file is "staged for commit" (or new or deleted as appropriate). Then it compares the files in the index to those in your work-tree; whatever is different is "not staged for commit". – torek Apr 04 '20 at 21:07
  • All of this means that something is going wrong with Git's index (`.git/index`) as it is not being re-filled from the `HEAD` commit when you do a `git reset`. If it were properly refilled from `HEAD`, there would be no "to be committed" section at all. – torek Apr 04 '20 at 21:08
  • Hmm. Well, I don't know what exactly went wrong with the index or how it got to that point, but I backed up `.git/index` then ran `rm .git/index` followed by `git reset`, and that cleared everything up. Everything listed in "Changes to be committed", "Changes not staged for commit", and "Untracked files" appears where it should – Mike S Apr 04 '20 at 21:25
  • If you want to add to your answer the bit about removing the index before resetting I'll mark it accepted – Mike S Apr 04 '20 at 21:27
  • OK - but *you should not have to do this*, so this points to a bug in your version of Git. – torek Apr 04 '20 at 21:31
  • In my case, with the same remote git-archive, when I use Windows, I have a long list of "deleted:"-Changes to be committed in that fresh, only cloned-from-remote local archive right from the beginning. I deleted it and started over - no luck. I tried `rm .git/index` and `git reset` - no luck. What helps partially is `git restore --staged *` to turn the files into "Changes not staged for commit", but there are still errors with "invalid path" - which seem to come from chars not allowed in Windows pathnames. But I didn't find a working solution yet. – Jochen Haßfurter Jan 13 '21 at 11:05
  • 1
    @JochenGebsattel: Windows is a problem, because Linux and Mac users can create files that you literally can't use. The files can be stored and manipulated inside Git (because it doesn't use ordinary files internally, at least, not the way the OS does) but you cannot take them out into your own file system (because the OS forbids these file names). I don't have or use Windows so cannot test any of the theoretical methods that *might* let you bypass this without having access to a Linux system, but it's definitely far easier to fix on the Linux system, as you found. – torek Jan 13 '21 at 18:18
3

In my case, there were some pathnames which didn't harm Linux' git, but unfortunately broke Windows' git. Anaconda is doing backups in the background and uses : in the filename. So there were Windows-bad filenames, git didn't clone anything from remote to Windows local and listed all files in the list of changed files to commit with "deleted:" - because my local folder was of course empty.

I just had to search these files from Anaconda / Jupyter Notebook in Ubuntu, rename or delete them, commit and push again to get my git-archive to Windows OS.

Realization from this experience is, that when there is a commit in Linux with filenames incompatible to the OS you're cloning to, git will correctly add those not-cloned files as immediate local changes to the index - even in an initial cloned archive.

Removing them from the changes-list was - for me - only possible with changing the filenames somewhere else outside Windows.

Hope this answer will help someone else...

Jochen Haßfurter
  • 875
  • 2
  • 13
  • 27