155

How do I create a patch with full context?

I tried --unified=2000, which gives 2000 lines of context:

git diff --unified=2000 branch master --no-prefix > patch

How do I include all the lines in the file without having to specify the maximum number of lines?

Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
balki
  • 26,394
  • 30
  • 105
  • 151
  • 3
    I posted the -U option to show the whole file, as a separate question http://stackoverflow.com/questions/28727424/for-git-diff-is-there-a-uinfinity-option-to-show-the-whole-file – Aleksandr Levchuk Feb 25 '15 at 19:05

7 Answers7

131

This seems to work pretty nicely:

git diff --no-prefix -U1000

With the caveat:

The -U flag specifies lines of context. You might need to increase this if there are more than 1000 lines between your changes.

approxiblue
  • 6,982
  • 16
  • 51
  • 59
c24w
  • 7,421
  • 7
  • 39
  • 47
  • 25
    The `-U` option you suggest is the same as the `--unified=` option used by the asker. The only difference is that you specify fewer lines of context, 1000, than the asker used, 2000. @balki wanted to know how to increase the number to infinity, yet you suggest cutting the number in half. Why? – Mr. Lance E Sloan May 03 '16 at 19:31
  • 6
    @LS: yep, I realise now, but overlooked that a couple of years ago. Still, it's a bit more apparent what's going on than in the question and seems to help the odd person who lands here. – c24w May 03 '16 at 19:38
  • Thanks for this, it also works great with `git show`! – Shakeel May 23 '16 at 18:38
  • but it doesn’t answer the question at all, which is “Is there a way to tell git to include all the lines in the file for patch without having to specify maximum lines?” – flying sheep Jan 19 '17 at 10:13
  • 3
    The `--no-prefix` option gets rid of the “/a/” and “/b/” destination prefixes that show up by default. (linked page) – luckydonald Dec 18 '17 at 09:26
79

I know this is old, but I also dislike hard-coded solutions, so I tested this:

git diff -U$(wc -l MYFILE)

Using -U seems to be the only way to approach the issue, but using a line count promises that it will work for even a small change in a very large file.

Ezra
  • 922
  • 7
  • 10
  • 1
    `<` is not necessary. `git diff -U$(wc -l MYFILE) MYFILE` – balki Nov 18 '16 at 22:12
  • 3
    Thanks @balki, I tried your suggestion and noticed that
    $(wc -l MYFILE)
    expands to the line count followed by the file name, so the second use of the filename can be omitted also. I'm updating my answer to reflect this.
    – Ezra Nov 22 '16 at 17:36
  • 12
    It's a diff, there are two version of the file. What if the version not on the disk was twice as long? Isn't -U with a really big number actually safer? – Eloff Aug 14 '18 at 13:29
  • @Eloff, that's true, the best way would be to max the lengths, since really big numbers still have the opposite problem. This solution assumes that no contiguous deletions larger than the current file size on disk were made. – Ezra Aug 15 '18 at 15:17
  • 1
    We could work something in from this answer to do a shell calculated max: https://unix.stackexchange.com/a/186703 - in my mind, a user is probably going to put this in their git config as an alias, so it is acceptable to be verbose. Ideally, there would be a --full-context diff option built into git. – Ezra Aug 15 '18 at 15:26
  • 7
    `git diff -U$(wc -l MYFILE | awk '{print $1}') MYFILE` is a better answer that correctly parses the output of `wc` by only getting the number of lines without whitespace, not relying on the unquoted output of a subshell to create two arguments, and works on macOS/BSD. – anishpatel Feb 18 '19 at 20:36
  • I believe this is a `Linux` command. What would you replace `wc` with on Windows? – Dr_Zaszuś Mar 04 '19 at 15:00
11

Note: git1.8.1rc1 announce (December 8th, 2012) includes:

A new configuration variable "diff.context" can be used to give the default number of context lines in the patch output, to override the hardcoded default of 3 lines.

so that could help, here, generate a more complete context.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • 7
    Yet that doesn't have an option to say 'All lines in the file' – balki Dec 11 '12 at 16:00
  • 3
    I suspect that putting a large number, that would simulate "all the lines" – VonC Dec 11 '12 at 16:04
  • 7
    "I suspect that putting a large number, that would simulate "all the lines"" ... except when it doesn't and then things break. All is synonymous with infinite, and a very large number is just that -- a number, not infinity. – Trenton Sep 25 '15 at 19:42
5

Got inspiration and so I added a git alias.

$ cat ~/.gitconfig | fgrep diff
        df = "!git diff -U$(wc -l \"$1\" | cut -d ' ' -f 1) \"$1\""
$ git df <file>

Update:

Just found git df does not work sometimes, due to directory change when executing git alias. (See git aliases operate in the wrong directory). Also @Moises Soto mentioned on macOS the wc command works differently (6 spaces at the front of the wc -l output) and suggested to use awk. So this is the updated version:

$ cat ~/.gitconfig | fgrep df
        df = "! [ \"$GIT_PREFIX\" != \"\" ] && cd \"$GIT_PREFIX\"; ~/bin/git_df.sh"
$ 
$ cat ~/bin/git_df.sh
#!/bin/bash
for FILE in $@; do
    git diff -U$(wc -l "${FILE}" | awk '{print $1}') "${FILE}"
done
exit 0
Yun Wu
  • 71
  • 1
  • 6
  • For a single line alias: df = "!cd -- ${GIT_PREFIX:-.}; git diff -U$(wc -l \"$1\" | cut -d ' ' -f 1) \"$1\"" – fizzyh2o Sep 15 '20 at 06:46
  • @fizzyh2o yes your version also works if `git df` only 1 file, however my version supports `git df` multiple files. – Yun Wu Feb 24 '22 at 22:56
2

This worked for me on macOS:

git diff -U$(wc -l main.htm | xargs)

see "How to trim whitespace from a Bash variable?"

Iulian Onofrei
  • 9,188
  • 10
  • 67
  • 113
Nakilon
  • 34,866
  • 14
  • 107
  • 142
2

I simply use

git diff -W Git.md

to list the full patch to a file. From man git diff:

-W, --function-context
Show whole function as context lines for each change.

Łukasz Rajchel
  • 261
  • 2
  • 4
  • That's a relevant switch to know about, however it doesn't necessarily include the whole file (most files will have more than one function). – David Cook Aug 23 '23 at 23:44
-1

Previously accepted solutions don't work for me when viewing a specific file/commit (the -U option seems to mess with rev/path parsing), but --inter-hunk-context= works in this case on git version 2.24.0:

git diff \
    --no-prefix \
    --inter-hunk-context=2000 \
    master -- \
        path/to/file.py

If you don't know the file size, you can of course find it with wc -l instead of hard-coding it:

git diff \
    --no-prefix \
    --inter-hunk-context=$(wc -l path/to/file.py) \
    master -- \
        path/to/file.py
stefco
  • 7
  • 1
  • 3
  • For me, this only shows three lines of context before the first change and three lines of context after the last change. – ma11hew28 Apr 12 '21 at 13:08
  • What version of git were you using? Did you replace "path/to/file.py" with your own file path? Just tested (the first variation with 2000 hardcoded) again on git 2.12.1 on windows and it works just fine. – stefco May 01 '21 at 23:49
  • Version 2.24.3. Yes, I did. But sorry, let me clarify my last comment: Your solution also (of course) shows all the lines between (and including) the changed lines, but I think @Machavity wants to "include all the lines in the file". For example, try your solution on a file with at least five lines and with all its changes after the first four lines. If what that shows you includes the first line of the file, then maybe you have the `diff.context` variable in your Git configuration file set to a number larger than the default of 3. – ma11hew28 May 03 '21 at 22:56