Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Git difftool in Windows to see list of all changed files in addition to file diffs (a la Kaleidoscope)?

When I do a git difftool, Kaleidoscope shows me all the files that have changed in the left sidebar:


(source: kaleidoscopeapp.com)

Is there any diff-tool in Windows that would show me such a list of files?

(I don't want the tool to open all the files at the same time in separate windows. I'm looking for a single window that will show me the list of files changed, and I should be able to click on a particular file to see its diff, as shown in the Kaleidoscope screenshot)

like image 201
Debajit Avatar asked Jul 19 '13 00:07

Debajit


People also ask

What is Difftool in git?

git difftool is a Git command that allows you to compare and edit files between revisions using common diff tools. git difftool is a frontend to git diff and accepts the same options and arguments.

How do I run git Difftool?

Run Git Difftool: Diff File from the Command Palette or use ⌥⌃D to diff the currently open file. Run Git Difftool: Diff Project from the Command Palette or use ⌃⇧D to diff the whole project.

What is the default git diff tool?

The default Diff Tool is vimdiff. Specifying a Diff Tool affects the git difftool command. The command git diff still performs diffing on the command-line.


1 Answers

You can use git difftool in a way which lists all the files (git1.8+ recommended):

git difftool --dir-diff

Copy the modified files to a temporary location and perform a directory diff on them.
This mode never prompts before launching the diff tool.

You can then integrate it with a BeyondCompare for instance.

Or with WinMerge:

[diff]
    tool = winmerge
[difftool "winmerge"]
    path = C:/Program Files (x86)/WinMerge/winmergeu.exe
    cmd = \"C:/Program Files (x86)/WinMerge/winmergeu.exe\" -r -u \"$LOCAL\" \"$REMOTE\"

All that with:

    $ git difftool [<commit> [<commit>]]

The only problem is the git diff-tool, on Windows, is described in this blog post, by nitoyon.

On Unix and MacOS, git difftool --dir-diff create a symbolic link to the working directory if a right-hand file has the same SHA1 as the file in the working directory. It's very useful when we modify right-hand files with a difftool.

On Windows, instead of creating symbolic links, git difftool --dir-diff copy back right-hand files to working directory after difftool program exits. I want to use symlinks on Git for Windows like Unix and MacOS.

Note: On Windows, administrator privileges is required to create symbolic links.

Run GitBash as an administrator, and enter following command.

$ git difftool -d --symlinks [<commit> [<commit>]]

If you want, create an alias on .gitconfig.

[alias]
    d = difftool -d --symlinks

But that requires:

  • to create a git mklink command:
C:\Program Files (x86)\Git\libexec\git-core\git-mklink:

#!/bin/sh

cmd.exe /c "mklink \"$2\" \"$1\"" > /dev/null
  • to patch msysgit 1.8.3:
cd /c/Program\ Files\ \(x86\)/Git/libexec/git-core/
$ patch < ~/git-difftool.patch

With git-difftool.patch:

    --- git-difftool    Sun Jun  2 11:28:06 2013
    +++ git-difftool    Tue Jul  9 00:42:02 2013
    @@ -283,7 +283,7 @@
                exit_cleanup($tmpdir, 1);
            }
            if ($symlinks) {
    -           symlink("$workdir/$file", "$rdir/$file") or
    +           !system("git", "mklink", "$workdir/$file", "$rdir/$file") or
                exit_cleanup($tmpdir, 1);
            } else {
                copy("$workdir/$file", "$rdir/$file") or
    @@ -448,7 +448,7 @@
        my $indices_loaded = 0;
    
        for my $file (@worktree) {
    -       next if $symlinks && -l "$b/$file";
    +       next if $symlinks;
            next if ! -f "$b/$file";
    
            if (!$indices_loaded) {

Before Git 2.34 (Q4 2021), "git difftool --dir-diff"(man) mishandled symbolic links.

See commit 5bafb35 (22 Sep 2021) by David Aguilar (davvid).
(Merged by Junio C Hamano -- gitster -- in commit 6a4f5da, 03 Oct 2021)

difftool: fix symlink-file writing in dir-diff mode

Reported-by: Alan Blotz
Helped-by: Đoàn Trần Công Danh
Signed-off-by: David Aguilar

The difftool dir-diff mode handles symlinks by replacing them with their readlink(2) values.
This allows diff tools to see changes to symlinks as if they were regular text diffs with the old and new path values.
This is analogous to what "git diff"(man) displays when symlinks change.

The temporary diff directories that are created initially contain symlinks because they get checked-out using a temporary index that retains the original symlinks as checked-in to the repository.

A bug was introduced when difftool was rewritten in C that made difftool write the readlink(2) contents into the pointed-to file rather than the symlink itself.
The write was going through the symlink and writing to its target rather than writing to the symlink path itself.

Replace symlinks with raw text files by unlinking the symlink path before writing the readlink(2) content into them.

When 18ec800 ("difftool: handle modified symlinks in dir-diff mode", 2017-03-15, Git v2.13.0-rc0 -- merge listed in batch #6) added handling for modified symlinks this bug got recorded in the test suite.
The tests included the pointed-to symlink target paths.
These paths were being reported because difftool was erroneously writing to them, but they should have never been reported nor written.

Correct the modified-symlinks test cases by removing the target files from the expected output.

And, still Git 2.34:

See commit 28c10ec, commit 8e2af8f, commit 2255c80, commit 4ac9f15 (30 Sep 2021) by David Aguilar (davvid).
See commit 77bd616 (23 Sep 2021), and commit 93a8ed2 (20 Sep 2021) by Junio C Hamano (gitster).
(Merged by Junio C Hamano -- gitster -- in commit 0cc4ec1, 11 Oct 2021)

difftool: refactor dir-diff to write files using helper functions

Signed-off-by: David Aguilar

Add a helpers function to handle the unlinking and writing of the dir-diff submodule and symlink stand-in files.

Use the helpers to implement the guts of the hashmap loops.
This eliminate duplicate code and safeguards the submodules hashmap loop against the symlink-chasing behavior that 5bafb35 ("difftool: fix symlink-file writing in dir-diff mode", 2021-09-22, Git v2.34.0 -- merge listed in batch #10) addressed.

The submodules loop should not strictly require the unlink() call that this is introducing to them, but it does not necessarily hurt them either beyond the cost of the extra unlink().

/* Write the file contents for the left and right sides of the difftool
 * dir-diff representation for submodules and symlinks. Symlinks and submodules
 * are written as regular text files so that external diff tools can diff them
 * as text files, resulting in behavior that is analogous to to what "git diff"
 * displays for symlink and submodule diffs.
 */
static void write_standin_files() {...}
like image 152
VonC Avatar answered Sep 20 '22 13:09

VonC