microsoft / vscode

Visual Studio Code
https://code.visualstudio.com
MIT License
164k stars 29.2k forks source link

Git gutters don't show on filenames that have changed case #103444

Open mattrossman opened 4 years ago

mattrossman commented 4 years ago

Steps to Reproduce:

~~1. Initialize a git repository~

  1. Add a capitalized filename, e.g. Counter.jsx
  2. Commit the file
  3. Make some changes in the file and save~~

The file will show as modified in the explorer, but the changes are not shown in the gutter. If you follow the same step but with a lowercase filename instead, the modifications will appear in the gutter. This is problematic for React projects where uppercase filenames are not uncommon.

Edit: See my modified instructions below

This issue was already brought up in #48714 and closed by 375411e, but the issue still occurs. I'm opening this new issue since the old one is locked.

Does this issue occur when all extensions are disabled?: Yes

joaomoreno commented 4 years ago

So, the same steps with a counter.jsx works just fine?

Can you show me the entire contents of Git: Show Git Output, as you run through both scenarios: with uppercase and with lowercase?

mattrossman commented 4 years ago

In testing this I realize the steps I originally shared are incorrect, and the issue is more complex that I thought. It is not an issue with Uppercase files specifically, rather it has to do with changing case more generally. Specifically, it seems to happen when VSCode creates the original file, as I couldn't recreate it with a simple list of shell commands.

Here are a new list of steps that I have verified to recreate the issue, along with the output you requested:

  1. Create a new project and open in VSCode

    mkdir project && cd project
    git init
    code .
  2. In the VSCode "Explorer" create a new file called "counter.jsx" with some content:

// counter.jsx
let foo;
  1. In the VSCode terminal, commit the file to git

    git add .
    git commit -m "Initial commit"

    Note that if you make edits to counter.jsx at this point, they will show in the gutter.

  2. Close the open file. In the VSCode terminal, rename the file (with git) and commit the change

    git mv counter.jsx Counter.jsx
    git commit -m "Rename"
  3. Click "Refresh" in the VSCode "Explorer" to see the changed filename

Now when you edit Counter.jsx, the changes don't show in the gutter.

You can follow the same steps using an originally uppercase filename that is renamed to lowercase to achieve the same results.

Here is the content of Git: Show Git Output after following the steps described here:

Click to view contents
Looking for git in: /usr/local/bin/git
Using git 2.27.0 from /usr/local/bin/git
> git rev-parse --show-toplevel
> git rev-parse --git-dir
Open repository: /Users/matt/src/temp/project
> git status -z -u
> git symbolic-ref --short HEAD
> git rev-parse master
fatal: ambiguous argument 'master': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git  [...] -- [...]'
> git for-each-ref --sort -committerdate --format %(refname) %(objectname)
> git remote --verbose
> git config --get commit.template
> git check-ignore -v -z --stdin
> git show --textconv :Other.jsx
> git ls-files --stage -- /Users/matt/src/temp/project/Other.jsx
> git config --global user.email
> git config --global user.name
> git status -z -u
> git symbolic-ref --short HEAD
> git rev-parse master
fatal: ambiguous argument 'master': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git  [...] -- [...]'
> git for-each-ref --sort -committerdate --format %(refname) %(objectname)
> git remote --verbose
> git config --get commit.template
> git check-ignore -v -z --stdin
> git show --textconv :counter.jsx
> git ls-files --stage -- /Users/matt/src/temp/project/counter.jsx
> git check-ignore -v -z --stdin
> git status -z -u
> git symbolic-ref --short HEAD
> git rev-parse master
fatal: ambiguous argument 'master': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git  [...] -- [...]'
> git for-each-ref --sort -committerdate --format %(refname) %(objectname)
> git remote --verbose
> git config --get commit.template
> git status -z -u
> git symbolic-ref --short HEAD
> git rev-parse master
fatal: ambiguous argument 'master': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git  [...] -- [...]'
> git for-each-ref --sort -committerdate --format %(refname) %(objectname)
> git remote --verbose
> git config --get commit.template
> git ls-files --stage -- /Users/matt/src/temp/project/counter.jsx
> git cat-file -s 7866c251d5ac36aaa11acd0c9a754538525cfe30
> git show --textconv :counter.jsx
> git status -z -u
> git symbolic-ref --short HEAD
> git rev-parse master
> git rev-parse --symbolic-full-name master@{u}
fatal: no upstream configured for branch 'master'
> git for-each-ref --sort -committerdate --format %(refname) %(objectname)
> git remote --verbose
> git config --get commit.template
> git status -z -u
> git symbolic-ref --short HEAD
> git rev-parse master
> git rev-parse --symbolic-full-name master@{u}
fatal: no upstream configured for branch 'master'
> git for-each-ref --sort -committerdate --format %(refname) %(objectname)
> git remote --verbose
> git config --get commit.template
> git show --textconv :counter.jsx
> git ls-files --stage -- /Users/matt/src/temp/project/counter.jsx
> git status -z -u
> git symbolic-ref --short HEAD
> git rev-parse master
> git rev-parse --symbolic-full-name master@{u}
fatal: no upstream configured for branch 'master'
> git for-each-ref --sort -committerdate --format %(refname) %(objectname)
> git remote --verbose
> git config --get commit.template
joaomoreno commented 4 years ago

Now when you edit Counter.jsx, the changes don't show in the gutter.

Can you try the same steps but rename the file to something else like counter-2.jsx. Do the changes appear in the gutter then?

mattrossman commented 4 years ago

Yes, if you rename it to something with the same case like counter-new.jsx then the changes appear in the gutter. Also, in that case there is no need to refresh the explorer to see the changed file name.

PavanKu commented 4 years ago

@mattrossman , @joaomoreno This issue looks related to issue#100763. Basically, vscode doesn't recognise the change in filename case. try

mv filename.js Filename.js // vscode File explorar and filename on tab won't reflect the change
mv filename.js fileName.js //vscode File explorar and filename on tab won't reflect the change
mv filename.js abc.js // vscode File explorar and filename on tab both recognise the change and update itself

That could be the reason why git gutter does not recognise the change.

Oran commented 4 years ago

Same Issue, but file name weren't changed It fixes itself if you clone the repo again from remote

joaomoreno commented 4 years ago

It fixes itself if you clone the repo again from remote

@mattrossman Can you confirm this?

mattrossman commented 4 years ago

I'm not sure what you want me to do, I'm not using a remote in my example so it's not clear when I should be pushing or cloning. @Oran seems to be having a different issue from me since they did not change filenames.

joaomoreno commented 4 years ago

Thanks @mattrossman, I can repro this on Windows as well. Sorry for not paying closer attention

@bpasero Here's another tough pickle for you. These are the steps: https://github.com/microsoft/vscode/issues/103444#issuecomment-666541057

What happens is: once the workbench knows about counter.jsx, it creates an editor model for it. When that file is renamed to Counter.jsx, and even after closing all text editors, upon opening the Counter.jsx text editor, its model still holds a reference to a URI which lists the lowercase variant of the file. Here's where SCM reads it and where this bug surfaces:

https://github.com/microsoft/vscode/blob/56adc7d930ad862c90f82964bb3f618d342ba177/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts#L1179-L1179

The bug surfaces since git is case sensitive, despite Windows being case insensitive.

More notes:

bpasero commented 4 years ago

This is a consequence of using IUriIdentityService for text models. Once this service is used to create a URI it will stay until you restart the app. We would need some way to invalidate cached URI maybe based on file events or other things to solve this properly.

jrieken commented 4 years ago

We would need some way to invalidate cached URI maybe based on file events or other things to solve this properly.

Unsure - rename is happening on a case-insensitive file system and therefore the path (in the sense of identity) isn't changing. @joaomoreno can you make your cache aware of uri identify rules? You can use IUriIdentityService#extUri and ResourceMap with the "right" toKey function

bpasero commented 4 years ago

I thought the issue here was that git itself is case-sensitive, even on Windows and we rely on git to do its work. I am not sure we get a hook into git's rules of how to compare paths.

joaomoreno commented 4 years ago

Exactly, @bpasero points to the right pickle. Git has a case sensitivity setting but this is a user configuration, we shouldn't really mess with it.

jrieken commented 4 years ago

Well, I guess the uri identity service won't help you then because it doesn't know what the actual representation is. If the git is so sensitive then I am afraid that you need to resolve the true casing before interacting with git.

NeeEoo commented 3 years ago

I was able to fix a file that had this problem by modifying the workspace state database.

By modifying memento/workbench.parts.editor, memento/workbench.editors.files.textFileEditor and codelens/cache2 to have the correct case on the filename.

While I wouldn't recommend editing the workspace state database, I am just saying it to help the developers to fix this bug.

PapaMarc commented 3 years ago

relative to other closed threads that poke around with this issue from various angles, this seems like the place at this point. Just wanted to share a related scenario so dev can appreciate relevance and get a sense of justification to address...

Whereas IIS servers are case insensitive, Unix webservers typically are not. I have some ooold web pages, that were hosted on IIS servers (privately in homes initially, then on public MS/IIS based hosters) for years... recently on moving them to GitHub pages hosting, lots of stuff 'broke' (404s) in the process.

Reason being, the underlying servers on GitHub pages are not hosted via IIS on Windows which is case insensitive (same for NameCheap shared hosting requiring respect for explicit casing). In attempting to fixup the filenames (or foldernames) to match href's to those files, when using rename in the VSCode Explorer pane against the git repo... while the change appears in that VSCode pane, it (just changing an uppercase letter to lower for example in an otherwise unchanged filename) doesn't commit up to GitHub. This thread also touches on some of the underlying issues.

A good workaround more/less highlighted in that thread (they achieve this slightly differently with git command line as seen in detail in that thread) which works well in the VSCode GUI is as follows: -1. rename file Name.jpg to name1.jpg <the desired casing propagates because of the additional char being a recognized change) -2. commit change made in step#1 (which i believe appears at 2 not 1 staged items) -3. rename file name1.jpg to name.jpg -4. commit change made in step3 (note: if you don't commit in #2, and just stage the change, and then stage the change in #3... then try to commit the 2 , actually 3, staged changes... you'll find the 2nd staging just nulls out your attempts to make any change and there's nothing to commit).

Thus, a vote of support for VSCode to recognize/support casing mods of an otherwise unchanged file or folder name be considered as a P3/'Nice to have' item, since non-explicit casing of folders or filenames used in URLs hosted on non-IIS servers results in 404 errors.

moshest commented 2 years ago

Please see a fix here: https://stackoverflow.com/a/11183844/518153

git mv casesensitive tmp
git mv tmp CaseSensitive

Basically apply this for any folder/file that cause problems..

Dionysusnu commented 2 years ago

I'd just like to point out the bug also stretches to the built-in diff view. If you open that, select a range, right click and use "Stage selected ranges", it gets staged in git as a new file that has the original casing, with the additions from the selected range as its only content.

While that original-case file is staged, the gutters do show up in the editor for the new-case file. Trying to stage something again in the diff view appends the additions from that range to the original-casing file.

It also creates an entry for the original-case file in the unstaged changes list. Viewing the diff of this shows it as the whole file being an addition, except for the range originally marked for staging.

Unstaging the original-case file in its entirety makes everything go back to the same state as before the first stage action, in which the file is shown only once in the changes window, and the gutters are not visible.

As suggested in https://github.com/microsoft/vscode/issues/103444#issuecomment-687071845, the bug stuck around if reloading while the file was open, but went away after closing all open file views and then reloading window.

o-l-a-v commented 2 months ago

Does it act different if case sensitivity is enabled for the directory? Can be done on NTFS and ReFS / Dev Drive.