-2

Solved, as explained in a comment under the accepted answer.

I have been using Git since years and I am really surprised that I there is one specific file that I can't add to the staging area in one of my repos! I don't want to delete and recreate the repo but to understand what is going on and fix it. Also, now I am worried that maybe there are other files that are not being added to the repo (or in other repos).

I have one repo in which I have just committed and pushed successfully a bunch of files, and then I have realized that one of them, init.el, didn't get uploaded. This is what I have:

  • Running git add init.el does not produce any output
  • The file (or a pattern matching it) is not specified in any .gitignore file (in the current folder, in a child folder, or in one of the parent directories until the root).
  • There is not parent Git repository that I have accidentally created and that is messing with that file
  • The file (or a patter matching it) is not listed in .git/info/exclude
  • The file (or a pattern matching it) does not appear when I run git ls-files --others -i --exclude-standard

I have then tried removing the file rm init.el, which correctly leads to

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
    modified:   .gitignore

Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
    deleted:    init.el

Then, I have tried doing git rm init.el, which again correctly led to

rm 'init.el'

But putting back the file and then adding the file with git add init.el shows no output, and the file is still missing from the staging area (I have checked this with git status, git diff --cached and by committing and pushing (see next line)). Trying to commit, push and double check what is going on in Github confirms that the file has not been added.

You never stops learning, is there anything standard that I am unaware of that may be triggering this behavior, or is this an error and so is there a way I can repair the repo?

EDIT, to answer one comment

  • pwd gives /Users/my_user/.my_spacemacs.d
  • cat .gitignore gives
.DS_Store
spacemacs_d_backup2020/
  • find . -name '.gitignore' gives
./spacemacs_d_backup2020/.gitignore
./.gitignore
  • finally, cat ./spacemacs_d_backup2020/.gitignore gives
.DS_Store
Nisba
  • 3,210
  • 2
  • 27
  • 46
  • 1
    what does your gitignore look like? – Liam Oct 26 '20 at 11:06
  • @Liam I have updated the answer – Nisba Oct 26 '20 at 11:09
  • 1
    “and the file is still missing from the staging area” How do you know what’s in the staging area? What command tells you that? – matt Oct 26 '20 at 11:14
  • `modified: .gitignore` - you modified the file because there was a pattern that matched your file? If so - you first have to commit `.gitignore` – Stanislav Bashkyrtsev Oct 26 '20 at 11:15
  • @matt I have used `git status` and `git diff --cached`, should I try something else? – Nisba Oct 26 '20 at 11:16
  • @StanislavBashkyrtsev no, I have added another random directory (`spacemacs_d_backup2020/`) – Nisba Oct 26 '20 at 11:16
  • 1
    Yes. Neither of those lists the contents of the staging area. – matt Oct 26 '20 at 11:21
  • @matt Ah, really!? I didn't know. What shall I use? Anyhow, I have tried committing and it was still missing. – Nisba Oct 26 '20 at 11:21
  • 3
    Everything you are saying is totally normal if init.el has already been committed and has not changed since then. – matt Oct 26 '20 at 11:23
  • Well I don’t know how you know what is “missing” either. – matt Oct 26 '20 at 11:24
  • 2
    We need a proper [mcve] here. There could be numerous problems here. – Liam Oct 26 '20 at 11:27
  • @matt of course. I am trying to create a MWE, I'll update the answer if I find it. – Nisba Oct 26 '20 at 12:38
  • "Anyhow, I have tried committing and it was still missing" Again I ask: _how do you know?_ What command did you use to learn what was in the commit? – matt Oct 26 '20 at 13:04
  • Is not reproducible. I tried and there was no problem to add `init.el`. Ergo, some important info is missing. – jschnasse Oct 26 '20 at 13:15
  • @Nisba what happens you when you run `git log -- init.el`? Do you get output? If so, that means your file is already commited (and hasn't changed, that's why you cannot add it _again_) – knittl Oct 26 '20 at 13:24
  • Solved as explained in the comment on the accepted answer. Nothing was broken, I was just operating on a messy repo... Thanks for the comments! – Nisba Oct 26 '20 at 21:51

1 Answers1

3

Let's talk about what git says when you talk to it. First, here's a folder with some files in it:

$ ls
a.txt   b.txt

Now I'll try to add a.txt to the staging area:

$ git add a.txt
$ 

Hmm, git didn't say anything. That's just like what you reported:

Running git add init.el does not produce any output

Darn. Why isn't it being added? Okay, let's try something else:

$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
    new file:   b.txt

Hmm, it didn't list a.txt. I'm getting worried! Okay, let's try a different way:

$ git diff --cached
diff --git a/b.txt b/b.txt
new file mode 100644
index 0000000..ce01362
--- /dev/null
+++ b/b.txt
@@ -0,0 +1 @@
+hello

Hmm, again it didn't mention a.txt. That's just like what you reported:

the file is still missing from the staging area (I have checked this with git status, git diff --cached

You also said:

The file (or a pattern matching it) does not appear when I run git ls-files --others -i --exclude-standard

OK, let me try that too:

$ git ls-files --others -i --exclude-standard
$

Nothing! Gosh, this is terrible. Why isn't a.txt being added to the staging area?

Because it's already in the staging area. The problem here is not that a.txt is not in the staging area; it's a misunderstanding of what the staging area is — possibly of what git itself is.

Here's the thing to remember:

  • Every commit contains all the files.

  • By default, every new commit contains all the same files as the previous commit. (The only differences will be files you have changed.)

  • By default, the staging area contains all the files in the last commit.

  • When you ask questions like git status or git diff, git only tells you what is new and different. It doesn't report what exists.

So that explains the mystery. Before all of this started, I already added and committed a.txt. So it is already in the staging area and it is already in the last commit.

So when I say git add a.txt, git says to itself: "Yep, well, a.txt is already in the staging area, and it hasn't changed, so nothing new here, move along, folks, move along" — and it doesn't reply.

And when I say git diff --cached, git doesn't mention a.txt because diff means "difference", and a.txt in the staging area is not different from a.txt in the last commit.

But none of that means that a.txt is not in the last commit or that it is not in the staging area. On the contrary, it means exactly the opposite. It means that it is in both of those places.

Now let's talk about lists.

Let's say we want to know what files are in the staging area. That's what git ls-files is for, plain and simple:

$ git ls-files
a.txt
b.txt

Look, there it is! a.txt is there after all! Okay, let's say we want to know what's in the most recent commit. Remember, what's in the most recent commit is also what was in the previous commit, and the commit before that, and the commit before that, except for any changes we may have performed each time. Every commit contains all the files, by default. So if a.txt has ever been committed, it is sufficient to see if it is in the latest commit. And here's how to do that:

$ git ls-tree --name-only HEAD
a.txt

There it is again!

So you see, a.txt was not failing to be added after all. It's just that I didn't understand what git was telling me.

Finally, you also say

Trying to commit, push and double check what is going on in Github confirms that the file has not been added

Well, I can't explain that one. But I can't look over your shoulder and see what you're doing at GitHub — and GitHub is hard to use. Maybe the problem is just one of not knowing how to look. If you are on a branch locally and you commit and push, and you then go to GitHub and hunt for a file, you might not find it, because GitHub by default doesn't show you the branch you were working on; it shows master (or main).

So here's my guess as to what's going on: You are on a branch locally, and you already added-and-committed init.el, perhaps quite a while ago, and you have not changed it since then. That, as I think I've demonstrated, would explain the phenomena you have described in your question.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • When I `git init test;cd $_;> a.txt;> b.txt;git add a.txt;git status` I see `a.txt` listed as a new file to be committed. – jthill Oct 26 '20 at 16:37
  • @jthill Yes, but that isn't the same as the situation I'm describing. – matt Oct 26 '20 at 16:42
  • So, found what it was... a combination of two things: first `.git/config` was referring to a wrong remote repo, since I moved the repo from a private server and Github and I did that a lot of time ago. Second, I feel quite embarrassed, I was actually operating in a clone of the repo in which the file was indeed added :( Great detective skills! And thanks for the explanations on the lists. And repetita iuvant. – Nisba Oct 26 '20 at 21:50