255

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.

S.L. Barth
  • 7,954
  • 71
  • 47
  • 62
Seba Illingworth
  • 5,026
  • 3
  • 24
  • 24

12 Answers12

228

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.

Tim Henigan
  • 55,120
  • 11
  • 81
  • 76
  • What's the difference between git-diffall and https://github.com/wmanley/git-meld? I tried both and they seem to provide identical functionality at first glance. – kynan Jul 25 '11 at 15:09
  • I mean apart from git-diffall respecting the difftool.tool setting, whereas git-meld has meld as hard coded as the diff tool. – kynan Jul 25 '11 at 15:19
  • 5
    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. – Douglas Dec 19 '11 at 23:29
  • This is the correct answer to the question. Super-easy install, works like a charm. – Bergius May 16 '12 at 15:22
  • 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 Jul 26 '12 at 23:14
  • 6
    **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). – Peter Rust Jul 27 '12 at 17:40
  • @PeterRust Since your comment was posted on '12, I am wondering what is the status regarding Beyond Compare in '15? – nowox Mar 24 '15 at 08:50
  • 4
    @coin I just tested with Beyond Compare 4 and --dir-diff appears to work with the supported bcomp.exe. – Peter Rust Mar 25 '15 at 13:38
  • @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: https://gist.github.com/nowox/0ee91465d94a52f6cd3e I think to implement it more seriously on my Git install – nowox Mar 25 '15 at 14:21
  • I did not have success with BC4 and `git difftool --dir-diff` but https://github.com/thenigan/git-diffall does integrate nicely with BC4. FYI I'm on Mac OS. – Tim D May 29 '15 at 09:27
  • 5
    Just commenting to say that `--dir-diff` works perfectly with Meld. From there, it will let you select and view diffs for individual files. – mkasberg Jun 30 '15 at 18:58
  • After closing the difftool, the changes are not reflected to the working dir. This is working for `git difftool --dir-diff` – DrumM Sep 25 '18 at 12:36
63

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.

Michael
  • 5,910
  • 4
  • 52
  • 74
Seba Illingworth
  • 5,026
  • 3
  • 24
  • 24
  • 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. – Carlos Rendon Apr 19 '10 at 16:24
  • 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. – Woody Zenfell III Aug 20 '10 at 16:30
  • 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. – Shane Mar 10 '11 at 00:31
  • 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. – kynan Jul 25 '11 at 15:23
  • 2
    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 – Dave C Nov 19 '15 at 15:02
  • 1
    @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? – m4l490n Jul 13 '17 at 15:04
  • @m4l490n I put the git-diffall script in a directory in my path. – Dave C Aug 03 '17 at 17:43
  • 2
    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 Sep 12 '17 at 11:07
  • 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` – nesdis Sep 12 '17 at 11:30
  • 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 – Bernardo Dal Corno Jan 27 '20 at 14:41
21

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.

Tom
  • 36,698
  • 31
  • 90
  • 98
  • 4
    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 Jul 25 '11 at 15:21
  • nice tool but horrible Windows install (as of early 2012). – Wernight Feb 01 '12 at 13:46
  • @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. :( – PKKid May 08 '12 at 15:20
  • 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. – kynan May 10 '12 at 06:41
  • 1
    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...) – namuol Dec 05 '13 at 03:20
3

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.

Seba Illingworth
  • 5,026
  • 3
  • 24
  • 24
3

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.

Khaja Minhajuddin
  • 6,236
  • 6
  • 43
  • 44
2

Noticed here that Araxis Merge has a '-nowait' command option:

-nowait Prevents compare from waiting for a comparison to be closed

Maybe this returns an immediate exit code and would work, anyone experienced this? Can't find similar option for BeyondCompare...

Community
  • 1
  • 1
Seba Illingworth
  • 5,026
  • 3
  • 24
  • 24
2

Diffuse also has VCS integration. It interoperates with a plethora of other VCS, including SVN, Mercurial, Bazaar, ... For Git, it will even show three panes if some but not all changes are staged. In the case of conflicts, there will even be four panes.

Screenshot of diffuse with staged and unstaged edits

Invoke it with

diffuse -m

in your Git working copy.

If you ask me, the best visual differ I've seen for a decade. (And I've tried meld, too.)

krlmlr
  • 22,030
  • 13
  • 107
  • 191
  • Can you tell which part of diffuse you liked, especially over meld? – musiphil Jul 24 '15 at 18:03
  • @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. – krlmlr Jul 26 '15 at 15:18
  • 1
    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. – mosh Feb 09 '18 at 03:46
2

The following works with meld and kdiff3

git difftool --dir-diff origin/branch1..origin/branch2

Opens all the files in a window that you can browse with ease. Can be used with changesets in place of origin/branch-name

eg: git difftool --dir-diff origin/master..24604fb72f7e16ed44115fbd88b447779cc74bb1

feltspar
  • 154
  • 1
  • 11
1

If all you want to do is open all the files that are currently modified, try something like:

vi $(git status | sed -n '/.*modified: */s///p')

If you are making commits of "complex sets of changes", you might want to reconsider your workflow. One of the really nice features of git is that it makes it easy for the developer to reduce complex change sets to a series of simple patches. Rather than trying to edit all of the files that are currently modified, you might want to look into

git add --patch
which will allow you to selectively stage hunks.
William Pursell
  • 174,418
  • 44
  • 247
  • 279
1

I've written a powershell script that will duplicate two working trees and compare with DiffMerge. So you can do:

GitNdiff master~3 .

To compare the master branch three checkins ago with the current working tree, for instance.

Its shiny and new and probably full of bugs. One drawback is that files in your working tree that have not been added yet are copied out to both working trees. It can also be slow.

http://github.com/fschwiet/GitNdiff

Frank Schwieterman
  • 23,338
  • 15
  • 87
  • 123
1

For those interested in using git-diffall on Mac OS X with Araxis, I forked the git-diffall project on github and added an AppleScript that wraps the Araxis Merge command. Note: this is a slightly modified clone of the araxisgitdiff file that ships with Araxis Merge for Mac OS X.

https://github.com/sorens/git-diffall

sorens
  • 4,880
  • 1
  • 27
  • 52
-2

You can use gitk and see all the differences at the same time

Aragorn
  • 843
  • 12
  • 25