I would like to track only a very restricted set of files, explicitly added to the repository using "git add -f". But how can I avoid having to use the "-f" again and again for files that are already in?
Sample:
% cat .gitignore
/*
% git status
On branch master
Your branch is up to date with 'origin/master'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: playlists/README
% git add playlists/README
The following paths are ignored by one of your .gitignore files:
playlists
hint: Use -f if you really want to add them.
hint: Turn this message off by running
hint: "git config advice.addIgnoredFile false"
% git check-ignore -v playlists/README
% echo $?
1
% git commit -a -m "fixed some typo"
[master 039d616] fixed some typo
1 file changed, 1 deletion(-)
% git status
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
% git version
git version 2.37.2
The playlists/README was explicitly mentioned on the command line, and yet I have to use "-f"? git commit wasn't so picky.
Of course I checked the man page. It says
A gitignore file specifies intentionally untracked files that Git should
ignore. Files already tracked by Git are not affected; see the NOTES
below for details.
But the "NOTES below" didn't tell. playlists/README is already tracked, and yet it was affected. Please excuse if I am too blind to see.
Every insightful comment is highly appreciated
CodePudding user response:
(Not an answer, I'm abusing the answer box to provide a formatted comment). Upd: reproduced. Shell script:
#! /bin/sh
set -e
git --version
git init test-add-gitignore-repo
cd test-add-gitignore-repo
echo
echo stage 1
mkdir testdir
echo test >testdir/test.txt
echo "/*" >.gitignore
git status
echo
echo stage 2
git add -f testdir/test.txt
git commit -m Test
git status
echo
echo stage 3
echo test2 >testdir/test.txt
git status
echo
echo stage 4
git add testdir/test.txt || :
git status
cd ..
rm -rf test-add-gitignore-repo
Output:
git version 2.30.2
Initialized empty Git repository in /home/phd/tmp/test-add-gitignore-repo/.git/
stage 1
On branch master
No commits yet
nothing to commit (create/copy files and use "git add" to track)
stage 2
[master (root-commit) 9ca248a] Test
1 file changed, 1 insertion( )
create mode 100644 testdir/test.txt
On branch master
nothing to commit, working tree clean
stage 3
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: testdir/test.txt
no changes added to commit (use "git add" and/or "git commit -a")
stage 4
The following paths are ignored by one of your .gitignore files:
testdir
hint: Use -f if you really want to add them.
hint: Turn this message off by running
hint: "git config advice.addIgnoredFile false"
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: testdir/test.txt
CodePudding user response:
I think you get this repeated warning because /*
rule instructs git to ignore the complete playlist/
directory, and even the presence of a tracked file inside that directory isn't accounted as a known exception to this rule (git
doesn't track directories, and I think a directory has no existence in the index).
The behavior on directories is hinted at by the documentation on .gitignore
rules (emphasis mine) :
- An optional prefix
"!"
which negates the pattern; any matching file excluded by a previous pattern will become included again. It is not possible to re-include a file if a parent directory of that file is excluded. Git doesn’t list excluded directories for performance reasons, so any patterns on contained files have no effect, no matter where they are defined. [...]
To have the "ignore everything except the files I explicitly added with -f
(at any directory level)" behavior, try the following gitignore file :
# ignore all files, but keep going down in directories
*
!*/
Another way to avoid the warning with a specific target on the playlist/
directory could be :
/*
!/playlist
/playlist/*