Can I use git diff on untracked files?

GitDiff

Git Problem Overview


Is it possible to ask git diff to include untracked files in its diff output, or is my best bet to use git add on the newly created files and the existing files I have edited, then use:

git diff --cached

?

Git Solutions


Solution 1 - Git

With recent git versions you can git add -N the file (or --intent-to-add), which adds a zero-length blob to the index at that location. The upshot is that your "untracked" file now becomes a modification to add all the content to this zero-length file, and that shows up in the "git diff" output.

git diff

echo "this is a new file" > new.txt
git diff

git add -N new.txt
git diff
diff --git a/new.txt b/new.txt
index e69de29..3b2aed8 100644
--- a/new.txt
+++ b/new.txt
@@ -0,0 +1 @@
+this is a new file

Sadly, as pointed out, you can't git stash while you have an --intent-to-add file pending like this. Although if you need to stash, you just add the new files and then stash them. Or you can use the emulation workaround:

git update-index --add --cacheinfo \
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 new.txt

(setting up an alias is your friend here).

Solution 2 - Git

I believe you can diff against files in your index and untracked files by simply supplying the path to both files.

git diff --no-index tracked_file untracked_file

Solution 3 - Git

For my interactive day-to-day gitting (where I diff the working tree against the HEAD all the time, and would like to have untracked files included in the diff), add -N/--intent-to-add is unusable, because it breaks git stash.

So here's my git diff replacement. It's not a particularly clean solution, but since I really only use it interactively, I'm OK with a hack:

d() {
    if test "$#" = 0; then
        (
            git diff --color
            git ls-files --others --exclude-standard |
                while read -r i; do git diff --color -- /dev/null "$i"; done
        ) | `git config --get core.pager`
    else
        git diff "$@"
    fi
}

Typing just d will include untracked files in the diff (which is what I care about in my workflow), and d args... will behave like regular git diff.

Notes:

  • We're using the fact here that git diff is really just individual diffs concatenated, so it's not possible to tell the d output from a "real diff" -- except for the fact that all untracked files get sorted last.

  • The only problem with this function is that the output is colorized even when redirected; but I can't be bothered to add logic for that.

  • I couldn't find any way to get untracked files included by just assembling a slick argument list for git diff. If someone figures out how to do this, or if maybe a feature gets added to git at some point in the future, please leave a note here!

Solution 4 - Git

Not 100% to the point, but if for some reason you don't want to add your files to the index as suggested by the accepted answer, here is another option:

If the files are untracked, obviously the diff is the whole file, so you can just view them with less:

less $(git ls-files --others --exclude-standard)

Navigate between them with :n and :p for next and previous..

Update from the comments: If you need a patch format you can also combine it with git diff:

git ls-files --others --exclude-standard -z | xargs -0 -n 1 git --no-pager diff /dev/null | less

You can also redirect the output to a file or use an other diff command in this case.

Solution 5 - Git

git add -A
git diff HEAD

Generate patch if required, and then:

git reset HEAD

Solution 6 - Git

For one file:

git diff --no-index /dev/null new_file

For all new files:

for next in $( git ls-files --others --exclude-standard ) ; do git --no-pager diff --no-index /dev/null $next; done;

As alias:

alias gdnew="for next in \$( git ls-files --others --exclude-standard ) ; do git --no-pager diff --no-index /dev/null \$next; done;"

For all modified and new files combined as one command:

{ git --no-pager diff; gdnew }

Solution 7 - Git

this works for me:

git add my_file.txt
git diff --cached my_file.txt
git reset my_file.txt

Last step is optional, it will leave the file in the previous state (untracked)

useful if you are creating a patch too:

  git diff --cached my_file.txt > my_file-patch.patch

Solution 8 - Git

Update: My answer is for staged and unstaged changes. Not tracked and untracked. See the accepted answer for the tracked/untracked information. Leaving here for posterity.

The following will give you only unstaged changes:

$ git diff

If you want both staged and unstaged changes, add HEAD to the command:

$ git diff HEAD

Solution 9 - Git

Usually when I work with remote location teams it is important for me that I have prior knowledge of what changes are done by other teams in the same file, before I follow git stages untrack-->staged-->commit for that I wrote a bash script which helps me to avoid unnecessary resolve merge conflict with remote team or make new local branch and compare and merge on main branch

#set -x 
branchname=`git branch | grep -F '*' |  awk '{print $2}'`
echo $branchname
git fetch origin ${branchname}
for file in `git status | grep "modified" | awk "{print $2}" `
do
echo "PLEASE CHECK OUT GIT DIFF FOR "$file 
git difftool FETCH_HEAD $file ;
done

In the above script I fetch remote main branch (not necessary it's master branch) to FETCH_HEAD them make a list of my modified files only and compare modified files to git difftool

Here many difftools are supported by git. I configure 'Meld Diff Viewer' for good GUI comparison.

Solution 10 - Git

Using the idea that you can stage the new file and you can diff the staged files, you can combine these two to see the diff. I find it simple to use.

  1. Add the files you want to see the diff.In your case, add only untracked files. You can optionally choose to add only those files you want to see the diff for.

    git stash && git add . && git stash pop 
    
  2. Diff the staged

    git diff --staged
    
  3. Reset the staged files if needed

    git reset
    

Combining all the above,

   git stash && git add . && git stash pop && git diff --staged && git reset 

Solution 11 - Git

If you happen to need this in the context of scripts that use git stash (i.e. a pre-commit git hook) this is working well for me with git v2.34.1 on macOS Big Sur:

# Stash unstaged changes
# NOTE: we always create a stash - possibly even a totally empty one.
git stash --keep-index --include-untracked --message="pre-commit auto-stash"
diffTracked=$(git diff --stat --staged stash@{0})
diffUntracked=$(git stash show --only-untracked stash@{0})
[[ $diffTracked || $diffUntracked ]] && {
  echo "Stashed diff:"
  # Ensure diffs have standard coloring:
  git diff --stat --staged stash@{0}
  git stash show --only-untracked stash@{0}
}

Solution 12 - Git

Assuming you do not have local commits,

git diff origin/master

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAndrew GrimmView Question on Stackoverflow
Solution 1 - GitaraqnidView Answer on Stackoverflow
Solution 2 - GitHaroldView Answer on Stackoverflow
Solution 3 - GitJo LissView Answer on Stackoverflow
Solution 4 - Gituser1587520View Answer on Stackoverflow
Solution 5 - GitAmol PujariView Answer on Stackoverflow
Solution 6 - GitradzimirView Answer on Stackoverflow
Solution 7 - GitAlejandro MorenoView Answer on Stackoverflow
Solution 8 - GitalairockView Answer on Stackoverflow
Solution 9 - GitadgView Answer on Stackoverflow
Solution 10 - GitArun GowdaView Answer on Stackoverflow
Solution 11 - GitDevin RhodeView Answer on Stackoverflow
Solution 12 - GitPradhanView Answer on Stackoverflow