git difftool, open all diff files immediately, not in serial
Asked Answered
I

13

287

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.

Ionization answered 3/8, 2009 at 0:52 Comment(5)
"git diff" or "git difftool"? You might want to post request on (open for all, and with varous web interface) git mailing list: [email protected]Overstuffed
I'm using "git difftool" to trigger external diff application. Thanks for the mailing list idea.Ionization
It would be helpful to know the platform. On a Unix-based platform, I would write a script to perform the diff and instruct git to use that script. In the script, I would simply run the diff in the background then let the script die.Baltimore
Windows platform, but thanks for the ideas Chris.Ionization
For mergetool: stackoverflow.com/questions/39259116/…Sidestep
I
71

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.

Ionization answered 3/8, 2009 at 0:53 Comment(12)
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.Hapten
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.Idealist
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.Desimone
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.Lackadaisical
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 CompareWichman
@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?Cannular
@Cannular I put the git-diffall script in a directory in my path.Wichman
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? difftoolMarseilles
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/gitMarseilles
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 btwUird
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" &Normand
This does not work for me in Linux. The problem is that in Linux the temporary file generated by git diff is immediately deleted after git diff quit, so the external tool won't be able to read the generated temporary file.Joachim
M
255

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.

Michaella answered 30/4, 2010 at 17:4 Comment(12)
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.Lackadaisical
I mean apart from git-diffall respecting the difftool.tool setting, whereas git-meld has meld as hard coded as the diff tool.Lackadaisical
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.Bunder
This is the correct answer to the question. Super-easy install, works like a charm.Leathers
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.Karlenekarlens
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).Karlenekarlens
@PeterRust Since your comment was posted on '12, I am wondering what is the status regarding Beyond Compare in '15?Alkene
@coin I just tested with Beyond Compare 4 and --dir-diff appears to work with the supported bcomp.exe.Karlenekarlens
@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 installAlkene
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.Phosphor
Just commenting to say that --dir-diff works perfectly with Meld. From there, it will let you select and view diffs for individual files.Kunlun
After closing the difftool, the changes are not reflected to the working dir. This is working for git difftool --dir-diffMafala
I
71

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.

Ionization answered 3/8, 2009 at 0:53 Comment(12)
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.Hapten
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.Idealist
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.Desimone
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.Lackadaisical
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 CompareWichman
@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?Cannular
@Cannular I put the git-diffall script in a directory in my path.Wichman
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? difftoolMarseilles
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/gitMarseilles
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 btwUird
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" &Normand
This does not work for me in Linux. The problem is that in Linux the temporary file generated by git diff is immediately deleted after git diff quit, so the external tool won't be able to read the generated temporary file.Joachim
C
24

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.

Claustrophobia answered 16/11, 2010 at 7:1 Comment(6)
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.Lackadaisical
nice tool but horrible Windows install (as of early 2012).Fondly
@Lackadaisical 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. :(Daiseydaisi
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.Lackadaisical
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...)Foliate
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.Sumption
I
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.

Ionization answered 3/8, 2009 at 0:58 Comment(0)
D
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.

Dexterdexterity answered 18/10, 2011 at 5:26 Comment(1)
Works great! As an added bonus it works exactly like hg meld. Thanks!Daiseydaisi
T
3

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

Te answered 29/6, 2018 at 19:26 Comment(0)
I
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...

Ionization answered 4/8, 2009 at 4:10 Comment(0)
D
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.)

Disharmonious answered 24/10, 2012 at 21:18 Comment(3)
Can you tell which part of diffuse you liked, especially over meld?Broody
@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.Disharmonious
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.Sumer
O
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.
Oniskey answered 11/8, 2009 at 11:30 Comment(0)
B
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

Blowtorch answered 1/7, 2010 at 16:9 Comment(0)
Z
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

Zacarias answered 17/2, 2011 at 10:54 Comment(0)
A
0

Wrote a small tool to open all files as tab pages in vim.

https://github.com/balki/vimtabdiff

Avertin answered 13/12, 2022 at 22:17 Comment(0)
V
-2

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

Velarize answered 11/8, 2009 at 2:50 Comment(1)
Yes I find gitk useful, but when it comes to diff-ing BC is what I want to see :)Ionization

© 2022 - 2024 — McMap. All rights reserved.