microsoft / microsoft/vscode

Diff editor ignores working-tree-encoding, showing entire file as modified

Open
#334,092 3 comments 0 reactions 1 assignee Claimed by @lszomoru View on GitHub
Dominant language
TypeScript
Stars
193k
Forks
42.4k
PR merge metrics
PR metrics pending

Description

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

- VS Code Version: 1.132.1 (c2d1b13fdc4a77628e5f3bb70173351c8f2fbad1) [x64]
- OS Version: Windows 11 Pro 25H2, build 26200.9278
- Git Version: 2.55.0.windows.3

The diff editor ignores the `working-tree-encoding` attribute from `.gitattributes`. When that attribute is set, git stores the blob UTF-8 encoded and re-encodes it on checkout, so the two sides of a diff legitimately live in different encodings. VS Code appears to decode both sides using the working tree encoding, which garbles the index/HEAD side and marks every line as changed even when one character was edited.

`git diff` on the command line is correct for the same file, so this is not a repository state problem.

## Steps to Reproduce

1. Create a repository where a file is stored UTF-8 in the object database but checked out as UTF-16 (PowerShell, so the encoding is unambiguous):

```powershell
mkdir wte-repro; cd wte-repro
git init
'sample.reg text working-tree-encoding=UTF-16 eol=crlf' | Set-Content .gitattributes -Encoding utf8

$enc = New-Object System.Text.UnicodeEncoding($false, $true) # UTF-16LE + BOM
[IO.File]::WriteAllLines("$PWD\sample.reg", @(
'Windows Registry Editor Version 5.00'
''
'[HKEY_CURRENT_USER\Test]'
'"Value"=dword:00000001'
), $enc)

git add -A; git commit -m "initial"
```

2. Edit a single character in the working tree file, preserving UTF-16LE + BOM:

```powershell
(Get-Content sample.reg) -replace 'dword:00000001', 'dword:00000002' | Set-Content sample.reg -Encoding unicode
```
3. Confirm git sees a one-line change: `git diff --stat sample.reg`
4. Run `code .` and select `sample.reg` in the Source Control view.

Expected: the diff shows one changed line, matching git diff.

Actual: the left-hand side renders as mojibake and the whole file is reported as modified, in the diff editor, the gutter, and the Source Control view.

## Notes

- Not specific to UTF-16 or to `.reg` files. Any working-tree-encoding value that differs from UTF-8 should reproduce it (UTF-16LE, UTF-16BE, SHIFT-JIS, and so on).
- Per the git documentation for working-tree-encoding, content is stored UTF-8 encoded in the object database, so decoding the index side as UTF-8 whenever the attribute is present would be correct. `git cat-file --filters :`, documented as showing content "as transformed by a filter configured via .gitattributes", may be the appropriate primitive for populating that side — worth confirming it covers encoding conversion and not only clean/smudge filters.
- Both available workarounds are lossy. Marking the files binary fixes the VS Code view but degrades git diff to "binary files differ"; dropping working-tree-encoding means storing UTF-16 blobs, which breaks textual diffs everywhere.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.