How can I diff binary files in git?

1,493

Solution 1

If you want to force git to show binary files diff as a plain text diff use --text option like so:

git diff --text

Solution 2

You can set a textconv config option for a filetype. See "Performing text diffs of binary files" in gitattributes(5). What you should use depends on the filetype.

Example 1:

Say you want to diff the contents of zip files. In that case you should put in one of the following files $XDG_CONFIG_HOME/git/config or $HOME/.gitconfig or $GIT_DIR/config .

[diff "zip"]
    textconv = unzip -v

Next time you ask for a diff on a zip file in a repo, it will call unzip -v on both version and diff the resulting text.

Example 2:

For pdf files you could use e.g. pdfinfo;

[diff "pdf"]
    textconv = pdfinfo

Example 3:

If there is no specific infomation utility for a filetype, you could e.g. use hexdump (comes with FreeBSD and OSX, also available on Linux):

[diff "bin"]
    textconv = hexdump -v -C

Solution 3

The answer from Roland Smith was helpful but is currently incomplete (see the comments) - there are two parts to this.

You can define a new diff commands in your repository's .git/config file or your personal global $XDG_CONFIG_HOME/git/config/.gitconfig (usually $HOME/.gitconfig) file, for example a hex diff command using hexdump:

[diff "hex"]
    textconv = hexdump -v -C
    binary = true

Next, you need to use the repository's .gitattributes file to tell git which files should be used with this special diff command:

# Binary files (no line-ending conversions), diff using hexdump
*.bin binary diff=hex

Like the .gitignore file, the .gitattributes file should be checked into your repository.

In my case I have several different file extensions which I want to treat as binary (e.g. avoid any line ending conversions if using git on Windows), and also see any differences via hexdump:

https://github.com/peterjc/galaxy_blast/commit/5ec4695e6c3da3926fb100ca006f0f3e88c53c3d

See also https://github.com/resin-io/etcher/pull/1367 for another example defining a hexdump diff command for use with image files.

Solution 4

To create a binary patch, a patch that works for binaries instead of just saying "Binary files differ", use

git diff --binary file1 file2

This produces a "GIT binary patch" using only ASCII characters (unlike --text), suitable for emailing.

Share:
1,493

Related videos on Youtube

denisiulian
Author by

denisiulian

Updated on September 18, 2022

Comments

  • denisiulian
    denisiulian over 1 year

    I have a column with buttons in a mat-table . Based on a value, I check if the button should be enabled or disabled and works fine. The problem is that if the user click on a disabled button, it will get an error. How I can disable the click event for a disabled button?

    <ng-container matColumnDef="download">
          <th mat-header-cell *matHeaderCellDef>download</th>
          <td mat-cell *matCellDef="let element">
              <mat-button  [disabled]="isDisabled(element.status)" (click)="download(element.value)"> download </mat-button>
          </td>
        </ng-container>
    
    • Paul Mikki
      Paul Mikki over 2 years
      Specify the error you're getting
    • denisiulian
      denisiulian over 2 years
      I'm getting an error from the backend. Because if the button is disabled, the click event shouldn't download something.
    • Jeremy Thille
      Jeremy Thille over 2 years
      As a workaround, in your download function, you can start with if(isDisabled(element.status)) return
    • Vimal Patel
      Vimal Patel over 2 years
      If the button clicked event is firing that means button it is not disabled at all.
  • Nick Retallack
    Nick Retallack over 10 years
    I could diff it in hex. I'd be happy enough just knowing how many bytes are different, or at what positions the bytes differ. I ended up using Hex Fiend by cloning my git repository so I could check out both versions of the file, because I couldn't figure out how to get git to launch the program.
  • Roland Smith
    Roland Smith over 10 years
    @NickRetallack: see added examples.
  • Roland Smith
    Roland Smith over 10 years
    @NickRetallack Example 3 only works for files with the bin extension. AFAIK, you'll have to set up a textconv for each individual file type.
  • Nick Retallack
    Nick Retallack over 10 years
    What do I do if there's no extension? Can I get it to work with libmagic instead?
  • Roland Smith
    Roland Smith over 10 years
    If you want to use libmagic, you'll have to look into the git source code to see if that works...
  • Justin Rowe
    Justin Rowe over 9 years
    I finally got this to work, after adding *.bin diff=bin to my .gitattributes
  • Tom Hale
    Tom Hale over 7 years
    For pdf, get both the header and text changes: [diff "pdf"] textconv="pdfinfo \"$1\";pdftotext \"$1\" - #" cachetextconv = true
  • Spencer Brereton
    Spencer Brereton over 7 years
    I've tried to get this working for MS .xlsm files, which are just zip files, and cannot get it to work. Doing unzip -v lists the content as expected, so not sure why it's not working. Git just continues to state Binary files a and b differ.
  • Roland Smith
    Roland Smith over 7 years
    @nilskp You need to both define a diff in your .gitconfig file and assign that attribute to a path in .gitattributes.
  • Spencer Brereton
    Spencer Brereton over 7 years
    @RolandSmith, yeah, I did.
  • Roland Smith
    Roland Smith over 7 years
    @nilskp Maybe you should post what you did as a question.
  • Spencer Brereton
    Spencer Brereton over 7 years
    @RolandSmith, I did exactly as described here. But I don't have this need right now, and not enough time to formulate it into a question.
  • Erhannis
    Erhannis over 5 years
    This appears to have discarded the changes to my file (and created an empty file where I wanted the committed version to be).
  • LightCC
    LightCC over 4 years
    You can set the .gitattributes globally as well (to go along with the [diff] entries in your global .gitconfig). If you make the .gitattributes local to the repo, then the user will have to modify his local .gitconfig repo settings because for security reasons those will not be pushed to the remote. Either way, each user has to update their local files/config somehow to enable this behavior. In .gitconfig under [core] add attributesfile = c:/users/<username>/.gitattributes or wherever you want to store it if you make it global (note the forwardslashes, even in windows).
  • paulkernfeld
    paulkernfeld over 3 years
    I love this answer because it's so simple and quick! One thing that I'm noticing is that it seemingly doesn't work for a merge conflict. If anyone knows how to get that to work, I think that would be a great addition.