git difftool, open all diff files immediately, not in serial

62,165

Solution 1

Here's what I settled on...

Copy the following code to a file called git-diffall (no extension):

#!/bin/sh
git diff --name-only "$@" | while read filename; do
    git difftool "$@" --no-prompt "$filename" &
done

Place the file in the cmd folder of your git install dir (eg C:\Program Files (x86)\Git\cmd)

And use like you would git diff:

git diffall
git diffall HEAD
git diffall --cached 
git diffall rev1..rev2
etc...

Notes: The key to it is the & param which tells the external diff command to run in a background task so files are processed immediately. In the case of BeyondCompare this opens one screen with each file in its own tab.

Solution 2

Starting with git v1.7.11, you can use git difftool --dir-diff to perform a directory diff.

This feature works well with Meld 3.14.2 for example, and lets you browse all modified files:

git difftool --dir-diff --tool=meld HEAD~ HEAD

This is a handy Bash function:

git-diff-meld() (
  git difftool --dir-diff --tool=meld "${1:-HEAD~}" "${2:-HEAD}"
)

The answer that follows applies to git installations older than v1.7.11.


This same question was asked on the git mail list.

I put together a shell script based on that email thread which performs a directory diff between arbitrary commits.

Starting with git v1.7.10, the git-diffall script is included in the contrib of the standard git installation.

For versions before v1.7.10, you can install from the git-diffall project on GitHub.

Here is the project description:

The git-diffall script provides a directory based diff mechanism for git. The script relies on the diff.tool configuration option to determine what diff viewer is used.

This script is compatible with all the forms used to specify a range of revisions to diff:

1) git diffall: shows diff between working tree and staged changes
2) git diffall --cached [<commit>]: shows diff between staged changes and HEAD (or other named commit)
3) git diffall <commit>: shows diff between working tree and named commit
4) git diffall <commit> <commit>: show diff between two named commits
5) git diffall <commit>..<commit>: same as above
6) git diffall <commit>...<commit>: show the changes on the branch containing and up to the second , starting at a common ancestor of both <commit>

Note: all forms take an optional path limiter [--] [<path>]

This script is based on an example provided by Thomas Rast on the Git list.

Solution 3

meld has a neat feature that if you give it a directory under source control (Git, Mercurial, Subversion, Bazaar and probably others) it will automatically list all the changed files and you can double-click to view the individual differences.

IMO it's much easier to type meld . and have it figure out the VCS than configure your VCS to launch meld. Plus you can use the same command no matter what VCS your project happens to be using, which is great if you switch between them a lot.

The only downside is it is slower for meld to scan for changes than to be passed the changes from git/hg/svn, though whether it's slow enough to be a problem will depend on how you're using it I'm sure.

Solution 4

git meld => https://github.com/wmanley/git-meld is an awesome script which will open a neat diff of all the files in a single window.

Solution 5

I did find this method (GitDiff.bat and GitDiff.rb) that copies the files out to old/new temp dirs and then does a folder compare on them.

But I'd rather view the working files directly (from the working dir), as BeyondCompare has the handy feature of being able to edit the file from within the diff window which is great for quick cleanups.

Edit: a similar method here in response to my question on the git mailing list.

Share:
62,165

Related videos on Youtube

Seba Illingworth
Author by

Seba Illingworth

On coding and cows, remoting from the farm

Updated on March 06, 2020

Comments

  • Seba Illingworth
    Seba Illingworth over 4 years

    The default git diff behavior is to open each diff file in serial (wait for previous file to be closed before opening next file).

    I'm looking for a way to open all the files at once - in BeyondCompare for example this would open all the files in tabs within the same BC window.

    This would make it easier to review a complex set of changes; flick back and forwards between the diff files and ignore unimportant files.

  • Seba Illingworth
    Seba Illingworth almost 15 years
    Yes I find gitk useful, but when it comes to diff-ing BC is what I want to see :)
  • koustubh
    koustubh about 14 years
    Thanks for posting. Unfortunatley, it doesn't work with WinMerge's -s option. All of the temp files except the first get deleted before WinMerge gets to look at them.
  • Woody Zenfell III
    Woody Zenfell III almost 14 years
    Carlos: I use WinMerge with Git. My approach was to add a 'sleep 1' after launching WinMerge (which in my case seems to already launch "in the background" - no need for &). This way the temporary file lives just long enough for WinMerge to pick it up once (except in weird cases). It does also mean that it takes 1 second per file to open them all. It's a nasty hack (I would never present it as an "answer"!), but an easy, fairly effective one.
  • Shane
    Shane over 13 years
    Thanks for the script! Works well with Araxis Merge on Mac with a slight adjustment to open Araxis first and then sleep for a second. Araxis also needs to be setup to open new merges in a tab.
  • kynan
    kynan almost 13 years
    What's the difference between git-diffall and github.com/wmanley/git-meld? I tried both and they seem to provide identical functionality at first glance.
  • kynan
    kynan almost 13 years
    I mean apart from git-diffall respecting the difftool.tool setting, whereas git-meld has meld as hard coded as the diff tool.
  • kynan
    kynan almost 13 years
    To me the main downside is that meld (for whatever reason) opens the diff in a new window instead of a new tab and after closing the diff, the file in the working directory opens in a new tab with an annoying popup message before.
  • kynan
    kynan almost 13 years
    Nice script, but I have 2 issues with it: It opens a new window for each file, which I don't like. Granted not every diff viewer supports it, but I want all diffs in the same window as tabs. The other issue is it doesn't work with text-only diff viewers like vimdiff. I suggest you add the --gui option to the difftool command line.
  • Douglas
    Douglas over 12 years
    I for one greatly appreciate your script. Frankly, I can't fathom why Git doesn't behave the right way in this regard (Mercurial does, and has done so for years), nor can I fathom the lack of interest from the Git community.
  • Wernight
    Wernight over 12 years
    nice tool but horrible Windows install (as of early 2012).
  • PKKid
    PKKid about 12 years
    Works great! As an added bonus it works exactly like hg meld. Thanks!
  • PKKid
    PKKid about 12 years
    @kynan This seems like the perfect solution for a VCS agnostic way of diffing if not for that annoying double window popup thing. Its a shame. :(
  • kynan
    kynan about 12 years
    A great feature of meld are its diff filters: ignore changes e.g. in comments or add/removal of blank lines, which git diff doesn't offer.
  • Bergius
    Bergius about 12 years
    This is the correct answer to the question. Super-easy install, works like a charm.
  • Peter Rust
    Peter Rust almost 12 years
    Regarding the git difftool --dir-diff command, be sure that your 3rd party tool blocks. If it returns immediately, git will tear down the temp folders before it finishes comparing them. For the Beyond Compare tool, this means to be sure your config is pointing to bcompare.exe, not bcomp.exe.
  • Peter Rust
    Peter Rust almost 12 years
    Update (regarding git difftool --dir-diff and Beyond Compare): I contacted Scooter Software (authors of Beyond Compare) and they say that bcompare.exe isn't a supported solution and may cause problems if there is more than one diff open at a time. They plan to add support for folder diffs to bcomp.exe in a future version (in the meantime, I'll continue using bcompare.exe as an unsupported workaround).
  • namuol
    namuol over 10 years
    I've used this approach for a year or so; it works fine for smaller projects but once you have a large project (i.e. lots of files) it is forbiddingly slow since it manually "scans" for git diffs (not sure why it takes this approach when git clearly can provide it with a list of files directly...)
  • nowox
    nowox over 9 years
    @PeterRust Since your comment was posted on '12, I am wondering what is the status regarding Beyond Compare in '15?
  • Peter Rust
    Peter Rust over 9 years
    @coin I just tested with Beyond Compare 4 and --dir-diff appears to work with the supported bcomp.exe.
  • nowox
    nowox over 9 years
    @PeterRust In the meantime I also investigated on Beyond Compare 3. It works but the temporary files created by git are unavailable on Beyond Compare 4 since the Perl script git-difftool finished before BC3. I quickly tried to bypass git-difftool with this snippet: gist.github.com/nowox/0ee91465d94a52f6cd3e I think to implement it more seriously on my Git install
  • Tim D
    Tim D about 9 years
    I did not have success with BC4 and git difftool --dir-diff but github.com/thenigan/git-diffall does integrate nicely with BC4. FYI I'm on Mac OS.
  • mkasberg
    mkasberg almost 9 years
    Just commenting to say that --dir-diff works perfectly with Meld. From there, it will let you select and view diffs for individual files.
  • musiphil
    musiphil almost 9 years
    Can you tell which part of diffuse you liked, especially over meld?
  • krlmlr
    krlmlr almost 9 years
    @musiphil: I like its simplicity -- it seems to have the exact set of features required to solve the task, not more, but also not less. (Like realignment of differences and tab size width.) I don't remember why I switched from meld, and I haven't used meld since then so I can't really compare them now.
  • user6741701
    user6741701 over 8 years
    For use on Linux, with Git 2.x, I had to make a slight modification: change "$filename" to "../$filename". Then it worked perfectly with Beyond Compare
  • m4l490n
    m4l490n almost 7 years
    @DaveC in the original thread it says to "store the file in the cmd folder of your git install" and proceeds with an example on windows. Where did you store the "git-diffall" file in Linux?
  • user6741701
    user6741701 almost 7 years
    @m4l490n I put the git-diffall script in a directory in my path.
  • nesdis
    nesdis almost 7 years
    Do we need to restart windows after adding git-diffall file to C:\Program Files\Git\cmd folder? I did exactly as instructed but upon doing $ git diffall git: 'diffall' is not a git command. See 'git --help'. Did you mean this? difftool
  • nesdis
    nesdis almost 7 years
    It is quite possible that C:\Program Files (x86)\Git\cmd is not in the path. In which case the git-diffall file needs to be placed in a folder that is in the path. eg: C:\SPB_Data\bin. In my case git was actually in the path /mingw64/bin/git
  • mosh
    mosh over 6 years
    Diffuse worked with git without any configuration. Diffuse -m opens single window with git diffs in different tabs; while other other tools need too much configuration to even get started.
  • jaques-sam
    jaques-sam over 5 years
    After closing the difftool, the changes are not reflected to the working dir. This is working for git difftool --dir-diff
  • Bernardo Dal Corno
    Bernardo Dal Corno over 4 years
    better than creating that file is to make this a git alias with shell function: diffall = !"f() { git diff --name-only "$@" | while read filename; do git difftool "$@" --no-prompt "$filename" & done }; f #". Nice solution btw
  • koppor
    koppor about 3 years
    I use it for comparing two branches. I checkout branch1. Then, with gitk, I navigate to branch2 and do a "mixed reset". Then, I can see with meld the files changed from branch1 to branch2.
  • SteveDonie
    SteveDonie over 2 years
    I wanted to be able to run this command anywhere in my repo, so I added this line at the beginning to calculate the root of the repo: GIT_ROOT=$(git rev-parse --show-toplevel) and then changed the difftool line so that the filename was prefixed with the root: git difftool "$@" --no-prompt "$GIT_ROOT/$filename" &