Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vimdiff Mergetool Regressed Between 2.36.1.windows.1 and 2.37.0.windows.1 #3945

Closed
1 task done
bambams opened this issue Jul 11, 2022 · 9 comments · Fixed by #3960
Closed
1 task done

Vimdiff Mergetool Regressed Between 2.36.1.windows.1 and 2.37.0.windows.1 #3945

bambams opened this issue Jul 11, 2022 · 9 comments · Fixed by #3960
Assignees
Milestone

Comments

@bambams
Copy link

bambams commented Jul 11, 2022

  • I was not able to find an open or closed issue matching what I'm seeing

Setup

  • Which version of Git for Windows are you using? Is it 32-bit or 64-bit?
$ git --version --build-options

git version 2.37.0.windows.1
cpu: x86_64
built from commit: 989c3a6832b035f6124b0a23da9c0f8f18afa550
sizeof-long: 4
sizeof-size_t: 8
shell-path: /bin/sh
feature: fsmonitor--daemon
  • Which version of Windows are you running? Vista, 7, 8, 10? Is it 32-bit or 64-bit?
$ cmd.exe /c ver

Microsoft Windows [Version 10.0.19044.1766]
  • What options did you set as part of the installation? Or did you choose the
    defaults?
# One of the following:
> type "C:\Program Files\Git\etc\install-options.txt"

Editor Option: VIM
Custom Editor Path:
Default Branch Option:
Path Option: CmdTools
SSH Option: OpenSSH
Tortoise Option: false
CURL Option: OpenSSL
CRLF Option: LFOnly
Bash Terminal Option: MinTTY
Git Pull Behavior Option: FFOnly
Use Credential Manager: Enabled
Performance Tweaks FSCache: Enabled
Enable Symlinks: Enabled
Enable Pseudo Console Support: Enabled
Enable FSMonitor: Enabled
  • Any other interesting things about your environment that might be related
    to the issue you're seeing?

None that come to mind.

Details

  • Which terminal/shell are you running Git from? e.g Bash/CMD/PowerShell/other

cmd.exe

git mergetool
  • What did you expect to occur after running these commands?

vim opens in diff mode with 4 buffers open in the default arrangement with the correct files open in each buffer.

  • What actually happened instead?

vim opens in diff mode with 7 buffers open. Paths with spaces in them are split into multiple buffers instead of opening the singular file per path, and so all of the buffers are empty because they refer to the wrong files.

  • If the problem was occurring with a specific repository, can you provide the
    URL to that repository to help us with testing?

N/A

I downgraded to git version 2.36.1.windows.1 as described below and the issue went away. I also tried 2.37.0.rc0.windows.1, 2.37.0.rc1.windows.1, and 2.37.0.rc2.windows.1, but none of them worked either.

$ git --version --build-options

git version 2.36.1.windows.1
cpu: x86_64
built from commit: e2ff68a2d1426758c78d023f863bfa1e03cbc768
sizeof-long: 4
sizeof-size_t: 8
shell-path: /bin/sh
feature: fsmonitor--daemon

> type "C:\Program Files\Git\etc\install-options.txt"

Editor Option: VIM
Custom Editor Path:
Default Branch Option:
Path Option: CmdTools
SSH Option: OpenSSH
Tortoise Option: false
CURL Option: OpenSSL
CRLF Option: LFOnly
Bash Terminal Option: MinTTY
Git Pull Behavior Option: FFOnly
Use Credential Manager: Enabled
Performance Tweaks FSCache: Enabled
Enable Symlinks: Enabled
Enable Pseudo Console Support: Enabled
Enable FSMonitor: Enabled```
@rimrul
Copy link
Member

rimrul commented Jul 12, 2022

This sounds like 0041797 is the culprit

@rimrul
Copy link
Member

rimrul commented Jul 12, 2022

At a glance that looks like it still quotes all the filename arguments to vim correctly.

@dscho
Copy link
Member

dscho commented Jul 12, 2022

@bambams could you please re-run after setting the environment variable GIT_TRACE=1, and paste the output verbatim? (If you are not able to divulge the exact file names, please do work on an MCVE.)

@dscho
Copy link
Member

dscho commented Jul 12, 2022

At a glance that looks like it still quotes all the filename arguments to vim correctly.

I fear that is not quite correct. Note the eval in 0041797#diff-bea8946dbd4d91f9de41e06b22d641c3bc1458891815f90b3796fe8b11d8a849R398-R399:

	eval "$merge_tool_path" \
			-f "$FINAL_CMD" "$LOCAL" "$BASE" "$REMOTE" "$MERGED"

At a first glance, it all looks quoted, right? But that's quoting it for the eval invocation, not for the invocation of the actual merge tool.

@rimrul
Copy link
Member

rimrul commented Jul 12, 2022

	eval "$merge_tool_path" \
			-f "$FINAL_CMD" "$LOCAL" "$BASE" "$REMOTE" "$MERGED"

At a first glance, it all looks quoted, right? But that's quoting it for the eval invocation, not for the invocation of the actual merge tool.

Good catch.

@dscho
Copy link
Member

dscho commented Jul 12, 2022

@bambams to find out whether our suspicion is correct, would you mind editing (as administrator) C:\Program Files\git\mingw64\libexec\git-core\mergetools\vimdiff by finding those two quoted lines and prefixing every double-quote character with a backslash, like so:

	eval \"$merge_tool_path\" \
			-f \"$FINAL_CMD\" \"$LOCAL\" \"$BASE\" \"$REMOTE\" \"$MERGED\"

and then running your git mergetool reproducer again?

@bambams
Copy link
Author

bambams commented Jul 12, 2022

create-merge-failure.cmd is a cmd command script that creates a demo repo to reproduce the issue in. It tracks a single file with a space in the file's name and attempts to merge conflicting branches for that file.

create-merge-failure.cmd.txt

This is the output I was able to capture from GIT_TRACE=1 git mergetool (in Git Bash, because the issue is reproducible in both shells):

git-mergetool-trace.txt

The shell prompt was overwritten in the scrollback so I'm not certain that's everything. Redirecting the output seemed to anger the command (perhaps because part of the output becomes Vim's UI?).

I tried escaping the quotes in the two eval commands of the vimdiff script, but it does not work either.

vimdiff.patch.txt

git-mergetool-trace-after-edit.txt

@landstander668
Copy link

@dscho I could be wrong, but wouldn't this require quoting doubling up the quoting (once for the execution, and once for the eval? Like:

eval "\"$merge_tool_path\"" \
			-f "\"$FINAL_CMD\"" "\"$LOCAL\"" "\"$BASE\"" "\"$REMOTE\"" "\"$MERGED\""

dscho added a commit to dscho/git that referenced this issue Jul 13, 2022
In 0041797 (vimdiff: new implementation with layout support,
2022-03-30), we introduced a completely new implementation of the
`vimdiff` backend for `git mergetool`.

In this implementation, we no longer call `vim` directly but we
accumulate in the variable `FINAL_CMD` an arbitrary number of commands
for `vim` to execute, which necessitates the use of `eval` to split the
commands properly into multiple command-line arguments.

That same `eval` command also needs to pass the paths to `vim`, and
while it looks as if they are quoted correctly, that quoting only
reaches the `eval` instruction and is lost after that, therefore paths
that contain whitespace characters (or other characters that are
interpreted by the POSIX shell) are handled incorrectly.

This is a simple reproducer:

	git init -b main bam-merge-fail
	cd bam-merge-fail
	echo a>"a file.txt"
	git add "a file.txt"
	git commit -m "added 'a file.txt'"
	echo b>"a file.txt"
	git add "a file.txt"
	git commit -m "diverged b 'a file.txt'"
	git checkout -b c HEAD~
	echo c>"a file.txt"
	git add "a file.txt"
	git commit -m "diverged c 'a file.txt'"
	git checkout main
	git merge c
	git mergetool --tool=vimdiff

With Git v2.37.0/v2.37.1, this will open 7 buffers, not four, and not
display the correct contents at all.

To fix this, let's not expand the variables containing the path
parameters before passing them to the `eval` command, but let that
command expand the variables instead.

This fixes git-for-windows#3945

Signed-off-by: Johannes Schindelin <[email protected]>
dscho added a commit to dscho/git that referenced this issue Jul 13, 2022
In 0041797 (vimdiff: new implementation with layout support,
2022-03-30), we introduced a completely new implementation of the
`vimdiff` backend for `git mergetool`.

In this implementation, we no longer call `vim` directly but we
accumulate in the variable `FINAL_CMD` an arbitrary number of commands
for `vim` to execute, which necessitates the use of `eval` to split the
commands properly into multiple command-line arguments.

That same `eval` command also needs to pass the paths to `vim`, and
while it looks as if they are quoted correctly, that quoting only
reaches the `eval` instruction and is lost after that, therefore paths
that contain whitespace characters (or other characters that are
interpreted by the POSIX shell) are handled incorrectly.

This is a simple reproducer:

	git init -b main bam-merge-fail
	cd bam-merge-fail
	echo a>"a file.txt"
	git add "a file.txt"
	git commit -m "added 'a file.txt'"
	echo b>"a file.txt"
	git add "a file.txt"
	git commit -m "diverged b 'a file.txt'"
	git checkout -b c HEAD~
	echo c>"a file.txt"
	git add "a file.txt"
	git commit -m "diverged c 'a file.txt'"
	git checkout main
	git merge c
	git mergetool --tool=vimdiff

With Git v2.37.0/v2.37.1, this will open 7 buffers, not four, and not
display the correct contents at all.

To fix this, let's not expand the variables containing the path
parameters before passing them to the `eval` command, but let that
command expand the variables instead.

This fixes git-for-windows#3945

Signed-off-by: Johannes Schindelin <[email protected]>
@dscho
Copy link
Member

dscho commented Jul 13, 2022

create-merge-failure.cmd is a cmd command script that creates a demo repo to reproduce the issue in. It tracks a single file with a space in the file's name and attempts to merge conflicting branches for that file.

create-merge-failure.cmd.txt

@bambams thank you for that reproducer, that helped be investigate and fix it within a reasonable time frame: gitgitgadget#1287

@dscho I could be wrong, but wouldn't this require quoting doubling up the quoting (once for the execution, and once for the eval? Like:

eval "\"$merge_tool_path\"" \
			-f "\"$FINAL_CMD\"" "\"$LOCAL\"" "\"$BASE\"" "\"$REMOTE\"" "\"$MERGED\""

@landstander668 At first, I thought that was the case, but I could not make it work. But then I looked around how eval is used elsewhere in Git, and in git-difftool--helper.sh, I found out how to do it better: instead of expanding $LOCAL and quoting it before passing it to eval and then somehow surrounding it with quotes, it is much better to let the eval expand the variable. In other words, instead of using double quotes, we should use single quotes to enclose a double-quoted variable expansion: '"$LOCAL"'. The single quotes are interpreted to pass "$LOCAL" verbatim to eval, which then expands it as a single command-line parameter.

dscho added a commit to dscho/git that referenced this issue Jul 13, 2022
In 0041797 (vimdiff: new implementation with layout support,
2022-03-30), we introduced a completely new implementation of the
`vimdiff` backend for `git mergetool`.

In this implementation, we no longer call `vim` directly but we
accumulate in the variable `FINAL_CMD` an arbitrary number of commands
for `vim` to execute, which necessitates the use of `eval` to split the
commands properly into multiple command-line arguments.

That same `eval` command also needs to pass the paths to `vim`, and
while it looks as if they are quoted correctly, that quoting only
reaches the `eval` instruction and is lost after that, therefore paths
that contain whitespace characters (or other characters that are
interpreted by the POSIX shell) are handled incorrectly.

This is a simple reproducer:

	git init -b main bam-merge-fail
	cd bam-merge-fail
	echo a>"a file.txt"
	git add "a file.txt"
	git commit -m "added 'a file.txt'"
	echo b>"a file.txt"
	git add "a file.txt"
	git commit -m "diverged b 'a file.txt'"
	git checkout -b c HEAD~
	echo c>"a file.txt"
	git add "a file.txt"
	git commit -m "diverged c 'a file.txt'"
	git checkout main
	git merge c
	git mergetool --tool=vimdiff

With Git v2.37.0/v2.37.1, this will open 7 buffers, not four, and not
display the correct contents at all.

To fix this, let's not expand the variables containing the path
parameters before passing them to the `eval` command, but let that
command expand the variables instead.

This fixes git-for-windows#3945

Signed-off-by: Johannes Schindelin <[email protected]>
gitster pushed a commit to git/git that referenced this issue Jul 13, 2022
In 0041797 (vimdiff: new implementation with layout support,
2022-03-30), we introduced a completely new implementation of the
`vimdiff` backend for `git mergetool`.

In this implementation, we no longer call `vim` directly but we
accumulate in the variable `FINAL_CMD` an arbitrary number of commands
for `vim` to execute, which necessitates the use of `eval` to split the
commands properly into multiple command-line arguments.

That same `eval` command also needs to pass the paths to `vim`, and
while it looks as if they are quoted correctly, that quoting only
reaches the `eval` instruction and is lost after that, therefore paths
that contain whitespace characters (or other characters that are
interpreted by the POSIX shell) are handled incorrectly.

This is a simple reproducer:

	git init -b main bam-merge-fail
	cd bam-merge-fail
	echo a>"a file.txt"
	git add "a file.txt"
	git commit -m "added 'a file.txt'"
	echo b>"a file.txt"
	git add "a file.txt"
	git commit -m "diverged b 'a file.txt'"
	git checkout -b c HEAD~
	echo c>"a file.txt"
	git add "a file.txt"
	git commit -m "diverged c 'a file.txt'"
	git checkout main
	git merge c
	git mergetool --tool=vimdiff

With Git v2.37.0/v2.37.1, this will open 7 buffers, not four, and not
display the correct contents at all.

To fix this, let's not expand the variables containing the path
parameters before passing them to the `eval` command, but let that
command expand the variables instead.

This fixes git-for-windows#3945

Signed-off-by: Johannes Schindelin <[email protected]>
Signed-off-by: Junio C Hamano <[email protected]>
dscho added a commit to dscho/git that referenced this issue Jul 14, 2022
In 0041797 (vimdiff: new implementation with layout support,
2022-03-30), we introduced a completely new implementation of the
`vimdiff` backend for `git mergetool`.

In this implementation, we no longer call `vim` directly but we
accumulate in the variable `FINAL_CMD` an arbitrary number of commands
for `vim` to execute, which necessitates the use of `eval` to split the
commands properly into multiple command-line arguments.

That same `eval` command also needs to pass the paths to `vim`, and
while it looks as if they are quoted correctly, that quoting only
reaches the `eval` instruction and is lost after that, therefore paths
that contain whitespace characters (or other characters that are
interpreted by the POSIX shell) are handled incorrectly.

This is a simple reproducer:

	git init -b main bam-merge-fail
	cd bam-merge-fail
	echo a>"a file.txt"
	git add "a file.txt"
	git commit -m "added 'a file.txt'"
	echo b>"a file.txt"
	git add "a file.txt"
	git commit -m "diverged b 'a file.txt'"
	git checkout -b c HEAD~
	echo c>"a file.txt"
	git add "a file.txt"
	git commit -m "diverged c 'a file.txt'"
	git checkout main
	git merge c
	git mergetool --tool=vimdiff

With Git v2.37.0/v2.37.1, this will open 7 buffers, not four, and not
display the correct contents at all.

To fix this, let's not expand the variables containing the path
parameters before passing them to the `eval` command, but let that
command expand the variables instead.

This fixes git-for-windows#3945

Signed-off-by: Johannes Schindelin <[email protected]>
@dscho dscho self-assigned this Jul 25, 2022
@dscho dscho added this to the Next release milestone Jul 25, 2022
dscho added a commit to git-for-windows/build-extra that referenced this issue Jul 25, 2022
A [regression in the `vimdiff` mode of `git
mergetool`](git-for-windows/git#3945)
has been [fixed](git-for-windows/git#3960).

Signed-off-by: Johannes Schindelin <[email protected]>
dscho added a commit that referenced this issue Jul 26, 2022
In 0041797 (vimdiff: new implementation with layout support,
2022-03-30), we introduced a completely new implementation of the
`vimdiff` backend for `git mergetool`.

In this implementation, we no longer call `vim` directly but we
accumulate in the variable `FINAL_CMD` an arbitrary number of commands
for `vim` to execute, which necessitates the use of `eval` to split the
commands properly into multiple command-line arguments.

That same `eval` command also needs to pass the paths to `vim`, and
while it looks as if they are quoted correctly, that quoting only
reaches the `eval` instruction and is lost after that, therefore paths
that contain whitespace characters (or other characters that are
interpreted by the POSIX shell) are handled incorrectly.

This is a simple reproducer:

	git init -b main bam-merge-fail
	cd bam-merge-fail
	echo a>"a file.txt"
	git add "a file.txt"
	git commit -m "added 'a file.txt'"
	echo b>"a file.txt"
	git add "a file.txt"
	git commit -m "diverged b 'a file.txt'"
	git checkout -b c HEAD~
	echo c>"a file.txt"
	git add "a file.txt"
	git commit -m "diverged c 'a file.txt'"
	git checkout main
	git merge c
	git mergetool --tool=vimdiff

With Git v2.37.0/v2.37.1, this will open 7 buffers, not four, and not
display the correct contents at all.

To fix this, let's not expand the variables containing the path
parameters before passing them to the `eval` command, but let that
command expand the variables instead.

This fixes #3945

Signed-off-by: Johannes Schindelin <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants