我可以在未跟踪的文件上使用git diff吗?


270

是否可以要求git diff在其diff输出中包括未跟踪的文件?还是我最好的选择是git添加我创建的新文件和我编辑过的现有文件,并使用

git diff --cached

Answers:


267

使用最新的git版本,您可以git add -N使用文件(或--intent-to-add),该文件会在该位置的索引中添加零长度的blob。结果是您的“未跟踪”文件现在变为修改,以将所有内容添加到此零长度文件中,并显示在“ git diff”输出中。

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

不幸的是,正如所指出的那样,git stash当您有一个--intent-to-add待处理的文件时无法这样做。尽管如果需要隐藏,则只需添加新文件,然后隐藏它们。或者,您可以使用仿真解决方法:

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

(在这里设置别名是您的朋友)。


事实证明,我的Git副本不够新,无法添加-N,但这回答了我的问题。
安德鲁·格林

1
您可以使用“ git update-index --add --cacheinfo 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 new.txt”来模拟“ git add -N new.txt”(我如何设法将其提供给错误的答案?)
araqnid


1
如果您有很多新文件,有没有简单的方法将它们全部添加然后进行比较?
维克

1
@Vicgit add -N .
Nathan

92

我相信您只需提供两个文件的路径,就可以与索引文件和未跟踪文件进行比较。

git diff --no-index tracked_file untracked_file

3
如果自上次提交以来创建了多个未跟踪的文件,这行得通吗?
安德鲁·格林

12
是的,完美的答案!那么我可以用git diff --no-index untracked_file_1 untracked_file_2得到git diff语法着色等上的diff ......美丽。
Colin D Bennett

40
我不明白您为什么要比较跟踪文件和不相关的未跟踪文件。如果您只想获取未跟踪文件的差异输出,则可以/dev/null改用:git diff --no-index -- /dev/null <untracked_file>

4
或者只是cat untracked_file_1,或者printf '\e[1;32m%s\e[0m\n' "$(cat untracked_file_1)"如果您确实需要绿色输出。:)(尽管请注意,命令替换会删除文件中的尾随换行符。)
通配符

8
这应该是公认的答案-不需要更改git的索引;正如原始作者所说,它有缺点
-DIMMSum

38

对于我的日常交互gitting(我一直将工作树与HEAD进行比较,并希望在diff中包含未跟踪的文件)add -N/--intent-to-add是无法使用的,因为它会中断 git stash

所以这是我的git diff替代品。这不是一个特别干净的解决方案,但是由于我实际上只以交互方式使用它,因此可以接受一些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
}

键入只会d将未跟踪的文件包含在diff中(这是我在工作流程中关心的内容),并且d args...表现得与常规一样git diff

笔记:

  • 我们在这里使用的事实git diff实际上只是各个差异的连接,因此不可能说出d“真实差异” 的输出-除了所有未跟踪的文件都最后排序的事实。
  • 此功能的唯一问题是,即使重定向,输出也会变色。但我不必为此添加逻辑。
  • 仅通过为组装一个光滑的参数列表,我找不到任何方法来获取包含未跟踪文件的方法git diff。如果有人知道如何执行此操作,或者git将来某个时候可能添加了功能,请在此处留下注释!

4
具有讽刺意味的是,我git update-index --add --cacheinfo 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 new.txt建议对较早的gits 使用的变通方法可与一起使用git stash,假设您已经在数据库中添加了e69de29bb,例如,尝试使用add -N以前的方法。因此,显然它git add -N在某些方面并不完全等同:tbh我不确定如何。
araqnid

2
test顺便说一句,您正在通过命令执行字符串比较,而不是数字相等性检查。不应该有任何影响,但test "$#" -eq 0更确切地说是预期的。
通配符

1
是的,看起来您仍然需要成对进行...但是可以将其伪造为一个,less因此您不必按q每个文件,并且感觉完全一样git diff,通过删除每个文件的分页(-P),然后将其添加回去(| less),保留颜色(--color=always)并将其解释为颜色(less -rless -R)。总而言之:do git -P diff --color=always -- /dev/null "$i"; done | less -r
palpalium

如果您希望以后再打扰,test -t 1(例如if [ -t 1 ]; then color_arg=--color; fi,诸如此类)是外壳检查其输出是否为终端的一种方法,这是决定颜色的有用方法。并xargs可能提供摆脱while循环的方法。您仍然需-n 1要这样做,因此它仍然会多次启动git,并且仍然需要以这种方式成对运行,但是...它摆脱了whileand read,所以也许更好?!?我把它留给读者。
林德斯

28

到目前为止还不是100%,但是如果由于某种原因您不想按照已接受的答案建议将文件添加到索引中,则可以使用另一种选择:

如果文件未跟踪,则差异显然是整个文件,因此您可以使用更少的内容查看它们:

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

:n:p在下一个和上一个之间导航。

更新评论:如果您需要补丁格式,也可以将其与结合使用git diff

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

在这种情况下,您也可以将输出重定向到文件或使用其他diff命令。


6
您还可以运行git diff /dev/null <untracked_tile>并以补丁程序格式获取补丁程序,而不是“仅”一个文件
SimSimY

2
这个答案结合git diff是完美的解决方案。
iwind

22
git add -A
git diff HEAD

如果需要,生成补丁,然后:

git reset HEAD

通过添加所有内容,这可能会丢失先前的(预)工作。尤其是如果一个人git add -p经常使用(顺便提一下,我通常建议这样做)的情况……这确实提供了一种做基本事情的方法,只是……应该注意的是,它可能会产生不必要的一面效果。
林德斯


9

使用此命令暂存和不暂存时,更改工作。暂存时新文件可以工作:

$ git diff HEAD

如果未暂存它们,则只会看到文件差异。


26
HEAD默认值,因此与git diff不能解决问题的相同。
Iulian Onofrei

4
这需要git add每个未跟踪的文件
SilvioQ,

如果您编辑这个答案,包括git add它是最简单的,如果你的使用情况是检查你刚才添加什么/想添加
KCD

8

对于一个文件:

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

对于所有新文件:

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

作为别名:

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

对于所有修改和新文件合并为一个命令:

{ git --no-pager diff; gdnew }

2

通常,当我与远程团队合作时,对我来说很重要的一点是,我必须先了解其他团队在同一文件中所做的更改,然后再执行git stage untrack-> staged-> commit那个我写了一个bash脚本,帮助我避免不必要的解决与远程团队合并冲突或建立新的本地分支并在主分支上进行比较和合并

#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

在上面的脚本中,我将远程主分支(不一定是其主分支)获取到FETCH_HEAD,它们仅列出我的修改文件,并将修改后的文件与git difftool进行比较

这里有很多git支持的difftool,我配置了'Meld Diff Viewer'以获得很好的GUI比较。


-9

假设您没有本地提交,

git diff origin/master

8
该问题要求提供git diff包含未跟踪文件的命令。此命令不包括它们。而且,是否存在本地提交与该问题绝对无关。
toon81 '16

JFTR,我git merge --squash mybranchgit diff master我展示了在未跟踪文件的变化。
muammar

2
这不可能。您似乎对“未跟踪”的含义感到困惑。未跟踪并不意味着文件在一个分支中被跟踪,而不是在另一个分支中,这意味着它不在任何地方以任何方式“在Git中”。不管你是南瓜还是没关系。git diff不会在未跟踪的文件中显示差异:因为它们是未跟踪的,所以根据定义,永远不会显示任何差异。这就是Git的工作方式。:)
toon81 '17
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.