index.add('.') adds even .git directory into the index, and adds files also with ./ prefix
Compare how stock git does it (related: there was this noise about security issue of having case-insensitive filesystems and .Git file in a repo):
$> rm -rf /tmp/123; mkdir /tmp/123; cd /tmp/123; git init; echo 1 > 1; git add 1; git status
Initialized empty Git repository in /tmp/123/.git/
On branch master
Initial commit
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: 1
and how GitPython (as of 1.0.1-74-gc8b8379 as in Debian):
$> rm -rf /tmp/123; mkdir /tmp/123; cd /tmp/123; git init; echo 1 > 1; python -c 'import git; r=git.Repo("/tmp/123"); r.index.add(".")'; git status
Initialized empty Git repository in /tmp/123/.git/
On branch master
Initial commit
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: ./.git/HEAD
new file: ./.git/config
new file: ./.git/description
new file: ./.git/hooks/applypatch-msg.sample
new file: ./.git/hooks/commit-msg.sample
new file: ./.git/hooks/post-update.sample
new file: ./.git/hooks/pre-applypatch.sample
new file: ./.git/hooks/pre-commit.sample
new file: ./.git/hooks/pre-push.sample
new file: ./.git/hooks/pre-rebase.sample
new file: ./.git/hooks/prepare-commit-msg.sample
new file: ./.git/hooks/update.sample
new file: ./.git/info/exclude
new file: ./.git/objects/49/8b267a8c7812490d6479839c5577eaaec79d62
new file: ./.git/objects/51/5f4836297fdf7567c066983c16e5eff598f7bd
new file: ./.git/objects/cb/089cd89a7d7686d284d8761201649346b5aa1c
new file: ./.git/objects/d0/0491fd7e5bb6fa28c517a0bb32b8b506539d4d
new file: ./1
Untracked files:
(use "git add <file>..." to include in what will be committed)
1
not sure why git says that 1 is untracked but ./1 was added... I guess also GitPython intricacy
Thanks for letting me know !
As I see the IndexFile implementation, it's definitely located in the plumbing area within the git ecosystem. Therefore I would expect it to do exactly as you say, which is what it does in this case as well.
The actual bug here seems to be left-over untracked file. I could imagine that for some reason, it added the ./ prefix to the filename into the index, which should in fact just be 1, not ./1.
In my own tests, I get a different, but also incorrect result:
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: ./.git/HEAD
new file: ./.git/config
new file: ./.git/description
new file: ./.git/hooks/applypatch-msg.sample
[...]
new file: ./.git/index
new file: ./.git/info/exclude
new file: ./.git/objects/41/42082bcb939bbc17985a69ba748491ac6b62a5
[...]
new file: ./1
new file: 1
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)
modified: ./.git/index
The latter should be fixed !
Meta
- git-python@7b85487
- git version 2.5.4 (Apple Git-61)
@Byron Thanks for looking into it. what is the proper way to stage content '.' for a commit then?
I think you would have to filter this path out by yourself. It is valid to pass in iterators, and a filter could look like (p for p in paths if not is_git_dir(p)).
Of course, this is something people would probably get wrong the first time, as it is somewhat unexpected, yet I believe plumbing shouldn't impose any limits, even if that means it's a loaded footgun.
This is still a thing v.v
Just ran into the same issue. Why is the .git folder pushed into the index? Thats totally weird!
okay there is some kind of workaround - thank god - but its still a very weird bug! https://github.com/gitpython-developers/GitPython/issues/292
Just for completeness, here is the link to the comment describing the workaround.