Skip to content

Lockable files left writable upon checkout when matching any filter in .gitignore, even with exception present #3183

@zach-r-d

Description

@zach-r-d

When a lockable file is checked out, it is not set to readonly if it matches any filter in .gitignore, even if there is an exception for it in .gitignore.

I've included an example below. Please let me know if there is any other information that would be helpful for me to provide. Thanks!

Example

Here, we have a simple repository with LFS (at the latest version) enabled for *.bin files, with all three files (.gitattributes, README.md, test.bin) committed on master and a clean working directory with no locks held. test.bin is read-only as expected.

$ git lfs version
git-lfs/2.5.1 (GitHub; linux amd64; go 1.10.3)

$ ls -la
total 24
drwxr-xr-x 3 zach domain^users 4096 Aug 14 15:37 .
drwxr-xr-x 8 zach domain^users 4096 Aug 14 15:00 ..
drwxr-xr-x 9 zach domain^users 4096 Aug 14 15:37 .git
-rw-r--r-- 1 zach domain^users   51 Aug 14 15:00 .gitattributes
-rw-r--r-- 1 zach domain^users   27 Aug 14 15:00 README.md
-r--r--r-- 1 zach domain^users    3 Aug 14 15:37 test.bin

$ cat .gitattributes 
*.bin filter=lfs diff=lfs merge=lfs -text lockable

$ git lfs locks --local

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.

nothing to commit, working directory clean

Removing and re-checkout-ing test.bin leaves it read-only, as expected.

$ rm test.bin && git checkout test.bin
rm: remove write-protected regular file ‘test.bin’? y

$ ls -la
total 24
drwxr-xr-x 3 zach domain^users 4096 Aug 14 15:38 .
drwxr-xr-x 8 zach domain^users 4096 Aug 14 15:00 ..
drwxr-xr-x 9 zach domain^users 4096 Aug 14 15:38 .git
-rw-r--r-- 1 zach domain^users   51 Aug 14 15:00 .gitattributes
-rw-r--r-- 1 zach domain^users   27 Aug 14 15:00 README.md
-r--r--r-- 1 zach domain^users    3 Aug 14 15:38 test.bin

However, adding a pattern to .gitignore that matches test.bin, then removing and re-checkout-ing test.bin causes it to be left writable.

$ echo '*t.bin' > .gitignore

$ rm test.bin && git checkout test.bin
rm: remove write-protected regular file ‘test.bin’? y

$ ls -la
total 28
drwxr-xr-x 3 zach domain^users 4096 Aug 14 15:39 .
drwxr-xr-x 8 zach domain^users 4096 Aug 14 15:00 ..
drwxr-xr-x 9 zach domain^users 4096 Aug 14 15:39 .git
-rw-r--r-- 1 zach domain^users   51 Aug 14 15:00 .gitattributes
-rw-r--r-- 1 zach domain^users    7 Aug 14 15:38 .gitignore
-rw-r--r-- 1 zach domain^users   27 Aug 14 15:00 README.md
-rw-r--r-- 1 zach domain^users    3 Aug 14 15:39 test.bin

Having a pattern in .gitignore that does not match test.bin makes it read-only again.

$ echo 'nomatch.txt' >.gitignore

$ rm test.bin && git checkout test.bin

$ ls -la
total 28
drwxr-xr-x 3 zach domain^users 4096 Aug 14 15:43 .
drwxr-xr-x 8 zach domain^users 4096 Aug 14 15:00 ..
drwxr-xr-x 9 zach domain^users 4096 Aug 14 15:43 .git
-rw-r--r-- 1 zach domain^users   51 Aug 14 15:00 .gitattributes
-rw-r--r-- 1 zach domain^users   12 Aug 14 15:43 .gitignore
-rw-r--r-- 1 zach domain^users   27 Aug 14 15:00 README.md
-r--r--r-- 1 zach domain^users    3 Aug 14 15:43 test.bin

Adding the matching pattern back into .gitignore along with an exception for test.bin still leaves it writable.

$ cat <<EOF >.gitignore
> *t.bin
> !test.bin
> EOF

$ rm test.bin && git checkout test.bin
rm: remove write-protected regular file ‘test.bin’? y

$ ls -la
total 28
drwxr-xr-x 3 zach domain^users 4096 Aug 14 15:44 .
drwxr-xr-x 8 zach domain^users 4096 Aug 14 15:00 ..
drwxr-xr-x 9 zach domain^users 4096 Aug 14 15:44 .git
-rw-r--r-- 1 zach domain^users   51 Aug 14 15:00 .gitattributes
-rw-r--r-- 1 zach domain^users   16 Aug 14 15:44 .gitignore
-rw-r--r-- 1 zach domain^users   27 Aug 14 15:00 README.md
-rw-r--r-- 1 zach domain^users    3 Aug 14 15:44 test.bin

$ 

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions